From c7ec1f44e9281db3a725f7da783b3dd2c7dece6e Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 16 Feb 2023 06:57:46 +0100 Subject: [PATCH] Option to enable/disable plugin by renaming file + cleanup new function: getAllPluginsJson removeComments removed - json doesnt allow for comments anyway --- admin/pages/plugins.php | 48 ++++++--- system/functions.php | 13 ++- system/libs/plugins.php | 127 +++++++++++++---------- system/templates/admin.plugins.html.twig | 17 ++- 4 files changed, 129 insertions(+), 76 deletions(-) diff --git a/admin/pages/plugins.php b/admin/pages/plugins.php index 65132118..6072455b 100644 --- a/admin/pages/plugins.php +++ b/admin/pages/plugins.php @@ -23,13 +23,29 @@ if (isset($_REQUEST['uninstall'])) { } else { error('Error while uninstalling plugin ' . $uninstall . ': ' . Plugins::getError()); } -} else if (isset($_FILES["plugin"]["name"])) { - $file = $_FILES["plugin"]; - $filename = $file["name"]; - $tmp_name = $file["tmp_name"]; - $type = $file["type"]; +} +else if (isset($_REQUEST['enable'])) { + $enable = $_REQUEST['enable']; + if (Plugins::enable($enable)) { + success('Successfully enabled plugin ' . $enable); + } else { + error('Error while enabling plugin ' . $enable . ': ' . Plugins::getError()); + } +} +else if (isset($_REQUEST['disable'])) { + $disable = $_REQUEST['disable']; + if (Plugins::disable($disable)) { + success('Successfully disabled plugin ' . $disable); + } else { + error('Error while disabling plugin ' . $disable . ': ' . Plugins::getError()); + } +} else if (isset($_FILES['plugin']['name'])) { + $file = $_FILES['plugin']; + $filename = $file['name']; + $tmp_name = $file['tmp_name']; + $type = $file['type']; - $name = explode(".", $filename); + $name = explode('.', $filename); $accepted_types = array('application/zip', 'application/x-zip-compressed', 'multipart/x-zip', 'application/x-compressed', 'application/octet-stream', 'application/zip-compressed'); if (isset($file['error'])) { @@ -90,21 +106,23 @@ if (isset($_REQUEST['uninstall'])) { } $plugins = array(); -foreach (get_plugins() as $plugin) { +foreach (get_plugins(true) as $plugin) { $string = file_get_contents(BASE . 'plugins/' . $plugin . '.json'); - $string = Plugins::removeComments($string); $plugin_info = json_decode($string, true); - if ($plugin_info == false) { + if (!$plugin_info) { warning('Cannot load plugin info ' . $plugin . '.json'); } else { + $disabled = (strpos($plugin, 'disabled.') !== false); + $pluginOriginal = ($disabled ? str_replace('disabled.', '', $plugin) : $plugin); $plugins[] = array( - 'name' => isset($plugin_info['name']) ? $plugin_info['name'] : '', - 'description' => isset($plugin_info['description']) ? $plugin_info['description'] : '', - 'version' => isset($plugin_info['version']) ? $plugin_info['version'] : '', - 'author' => isset($plugin_info['author']) ? $plugin_info['author'] : '', - 'contact' => isset($plugin_info['contact']) ? $plugin_info['contact'] : '', - 'file' => $plugin, + 'name' => $plugin_info['name'] ?? '', + 'description' => $plugin_info['description'] ?? '', + 'version' => $plugin_info['version'] ?? '', + 'author' => $plugin_info['author'] ?? '', + 'contact' => $plugin_info['contact'] ?? '', + 'file' => $pluginOriginal, + 'enabled' => !$disabled, 'uninstall' => isset($plugin_info['uninstall']) ); } diff --git a/system/functions.php b/system/functions.php index a2c7d202..d1184272 100644 --- a/system/functions.php +++ b/system/functions.php @@ -791,16 +791,21 @@ function get_templates() * Generates list of installed plugins * @return array $plugins */ -function get_plugins() +function get_plugins($disabled = false): array { - $ret = array(); + $ret = []; $path = PLUGINS; - foreach(scandir($path, 0) as $file) { + foreach(scandir($path, SCANDIR_SORT_DESCENDING) as $file) { $file_ext = pathinfo($file, PATHINFO_EXTENSION); $file_name = pathinfo($file, PATHINFO_FILENAME); - if ($file === '.' || $file === '..' || $file === 'disabled' || $file === 'example.json' || $file_ext !== 'json' || is_dir($path . $file)) + if ($file === '.' || $file === '..' || $file === 'example.json' || $file_ext !== 'json' || is_dir($path . $file)) { continue; + } + + if (!$disabled && strpos($file, 'disabled.') !== false) { + continue; + } $ret[] = str_replace('.json', '', $file_name); } diff --git a/system/libs/plugins.php b/system/libs/plugins.php index 3d9792b9..420c1cdd 100644 --- a/system/libs/plugins.php +++ b/system/libs/plugins.php @@ -10,7 +10,7 @@ */ defined('MYAAC') or die('Direct access not allowed!'); -function is_sub_dir($path = NULL, $parent_folder = SITE_PATH) { +function is_sub_dir($path = NULL, $parent_folder = BASE) { //Get directory path minus last folder $dir = dirname($path); @@ -41,9 +41,9 @@ function is_sub_dir($path = NULL, $parent_folder = SITE_PATH) { use Composer\Semver\Semver; class Plugins { - private static $warnings = array(); + private static $warnings = []; private static $error = null; - private static $plugin_json = array(); + private static $plugin_json = []; public static function getRoutes() { @@ -56,22 +56,8 @@ class Plugins { } $routes = []; - foreach(get_plugins() as $filename) { - $string = file_get_contents(PLUGINS . $filename . '.json'); - $string = self::removeComments($string); - $plugin = json_decode($string, true); - self::$plugin_json = $plugin; - if ($plugin == null) { - self::$warnings[] = 'Cannot load ' . $filename . '.json. File might be not a valid json code.'; - continue; - } - - if(isset($plugin['enabled']) && !getBoolean($plugin['enabled'])) { - self::$warnings[] = 'Skipping ' . $filename . '... The plugin is disabled.'; - continue; - } - - $warningPreTitle = 'Plugin: ' . $filename . ' - '; + foreach(self::getAllPluginsJson() as $plugin) { + $warningPreTitle = 'Plugin: ' . $plugin['name'] . ' - '; if (isset($plugin['routes'])) { foreach ($plugin['routes'] as $_name => $info) { @@ -161,28 +147,14 @@ class Plugins { } $hooks = []; - foreach(get_plugins() as $filename) { - $string = file_get_contents(PLUGINS . $filename . '.json'); - $string = self::removeComments($string); - $plugin = json_decode($string, true); - self::$plugin_json = $plugin; - if ($plugin == null) { - self::$warnings[] = 'Cannot load ' . $filename . '.json. File might be not a valid json code.'; - continue; - } - - if(isset($plugin['enabled']) && !getBoolean($plugin['enabled'])) { - self::$warnings[] = 'Skipping ' . $filename . '... The plugin is disabled.'; - continue; - } - + foreach(self::getAllPluginsJson() as $plugin) { if (isset($plugin['hooks'])) { foreach ($plugin['hooks'] as $_name => $info) { if (defined('HOOK_'. $info['type'])) { $hook = constant('HOOK_'. $info['type']); $hooks[] = ['name' => $_name, 'type' => $hook, 'file' => $info['file']]; } else { - self::$warnings[] = 'Plugin: ' . $filename . '. Unknown event type: ' . $info['type']; + self::$warnings[] = 'Plugin: ' . $plugin['name'] . '. Unknown event type: ' . $info['type']; } } } @@ -195,6 +167,41 @@ class Plugins { return $hooks; } + public static function getAllPluginsJson($disabled = false) + { + $cache = Cache::getInstance(); + if ($cache->enabled()) { + $tmp = ''; + if ($cache->fetch('plugins', $tmp)) { + return unserialize($tmp); + } + } + + $plugins = []; + foreach (get_plugins($disabled) as $filename) { + $string = file_get_contents(PLUGINS . $filename . '.json'); + $plugin = json_decode($string, true); + self::$plugin_json = $plugin; + if ($plugin == null) { + self::$warnings[] = 'Cannot load ' . $filename . '.json. File might be not a valid json code.'; + continue; + } + + if (isset($plugin['enabled']) && !getBoolean($plugin['enabled'])) { + self::$warnings[] = 'Skipping ' . $filename . '... The plugin is disabled.'; + continue; + } + + $plugins[] = $plugin; + } + + if ($cache->enabled()) { + $cache->set('plugins', serialize($plugins), 600); + } + + return $plugins; + } + public static function install($file) { global $db; @@ -235,7 +242,6 @@ class Plugins { } $string = file_get_contents($file_name); - $string = self::removeComments($string); $plugin_json = json_decode($string, true); self::$plugin_json = $plugin_json; if ($plugin_json == null) { @@ -435,7 +441,35 @@ class Plugins { return false; } - public static function uninstall($plugin_name) + public static function enable($pluginFileName): bool + { + return self::enableDisable($pluginFileName, true); + } + + public static function disable($pluginFileName): bool + { + return self::enableDisable($pluginFileName, false); + } + + private static function enableDisable($pluginFileName, $enable): bool + { + $filenameJson = $pluginFileName . '.json'; + $fileExist = is_file(PLUGINS . ($enable ? 'disabled.' : '') . $filenameJson); + if (!$fileExist) { + self::$error = 'Cannot ' . ($enable ? 'enable' : 'disable') . ' plugin: ' . $pluginFileName . '. File does not exist.'; + return false; + } + + $result = rename(PLUGINS . ($enable ? 'disabled.' : '') . $filenameJson, PLUGINS . ($enable ? '' : 'disabled.') . $filenameJson); + if (!$result) { + self::$error = 'Cannot ' . ($enable ? 'enable' : 'disable') . ' plugin: ' . $pluginFileName . '. Permission problem.'; + return false; + } + + return true; + } + + public static function uninstall($plugin_name): bool { $filename = BASE . 'plugins/' . $plugin_name . '.json'; if(!file_exists($filename)) { @@ -443,9 +477,8 @@ class Plugins { return false; } $string = file_get_contents($filename); - $string = self::removeComments($string); $plugin_info = json_decode($string, true); - if($plugin_info == false) { + if(!$plugin_info) { self::$error = 'Cannot load plugin info ' . $plugin_name . '.json'; return false; } @@ -527,22 +560,6 @@ class Plugins { return self::$plugin_json; } - public static function removeComments($string) { - $string = preg_replace('!/\*.*?\*/!s', '', $string); - $string = preg_replace('/\n\s*\n/', "\n", $string); - // Removes multi-line comments and does not create - // a blank line, also treats white spaces/tabs - $string = preg_replace('!^[ \t]*/\*.*?\*/[ \t]*[\r\n]!s', '', $string); - - // Removes single line '//' comments, treats blank characters - $string = preg_replace('![ \t]*//.*[ \t]*[\r\n]!', '', $string); - - // Strip blank lines - $string = preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $string); - - return $string; - } - /** * Install menus * Helper function for plugins diff --git a/system/templates/admin.plugins.html.twig b/system/templates/admin.plugins.html.twig index 07d2c044..bffb82f3 100644 --- a/system/templates/admin.plugins.html.twig +++ b/system/templates/admin.plugins.html.twig @@ -6,6 +6,7 @@ + @@ -16,6 +17,17 @@ {% for plugin in plugins %} + @@ -29,7 +41,8 @@ - {% endif %} + {% endif %} + {% endfor %} @@ -39,6 +52,6 @@
Enabled Name Version Author
+ {% if plugin.enabled %} + + Enabled + + {% else %} + + Disabled + + {% endif %} + {{ plugin.name }}
{{ plugin.description|raw }}