diff --git a/bl-kernel/abstract/plugin.class.php b/bl-kernel/abstract/plugin.class.php index 16be0ec1..2003bb95 100644 --- a/bl-kernel/abstract/plugin.class.php +++ b/bl-kernel/abstract/plugin.class.php @@ -296,6 +296,20 @@ class Plugin { return $this->save(); } + public function configure($args) + { + foreach ($this->db as $field=>$value) { + if (isset($args[$field])) { + $finalValue = Sanitize::html( $args[$field] ); + if ($finalValue==='false') { $finalValue = false; } + elseif ($finalValue==='true') { $finalValue = true; } + settype($finalValue, gettype($value)); + $this->db[$field] = $finalValue; + } + } + return $this->save(); + } + public function setField($field, $value) { $this->db[$field] = Sanitize::html($value); diff --git a/bl-kernel/admin/controllers/plugins-position.php b/bl-kernel/admin/controllers/plugins-position.php index 164e113f..952fa002 100644 --- a/bl-kernel/admin/controllers/plugins-position.php +++ b/bl-kernel/admin/controllers/plugins-position.php @@ -1,7 +1,7 @@ <?php defined('BLUDIT') or die('Bludit CMS.'); // ============================================================================ -// Check role +// Authorization // ============================================================================ checkRole(array('admin')); @@ -11,19 +11,8 @@ checkRole(array('admin')); // ============================================================================ // ============================================================================ -// Main before POST -// ============================================================================ -if ($_SERVER['REQUEST_METHOD'] == 'POST') { - changePluginsPosition(explode(',',$_POST['plugin-list'])); - Redirect::page('plugins-position'); -} -// ============================================================================ -// POST Method +// Main // ============================================================================ -// ============================================================================ -// Main after POST -// ============================================================================ - -// Title of the page -$layout['title'] .= ' - '.$L->g('Plugins'); \ No newline at end of file +// HTML <title> +$layout['title'] = $L->g('Plugin') . ' - ' . $layout['title']; diff --git a/bl-kernel/admin/views/dashboard.php b/bl-kernel/admin/views/dashboard.php index 881ff96d..ae2d7308 100644 --- a/bl-kernel/admin/views/dashboard.php +++ b/bl-kernel/admin/views/dashboard.php @@ -27,7 +27,7 @@ <div id="dashboard" class="container-fluid"> <div class="row"> <div class="col-7"> - <?php Theme::plugins('dashboard') ?> + <?php execPluginsByHook('dashboard') ?> </div> <div class="col-5"> diff --git a/bl-kernel/admin/views/plugins-position.php b/bl-kernel/admin/views/plugins-position.php index 79361e2e..34ac777d 100644 --- a/bl-kernel/admin/views/plugins-position.php +++ b/bl-kernel/admin/views/plugins-position.php @@ -1,51 +1,80 @@ <?php defined('BLUDIT') or die('Bludit CMS.'); ?> -<?php echo Bootstrap::formOpen(array('id'=>'jsform', 'class'=>'tab-content')); ?> +<script> + // ============================================================================ + // Variables for the view + // ============================================================================ -<div class="align-middle"> - <div class="float-end mt-1"> - <button type="button" class="btn btn-primary btn-sm jsbuttonSave" name="save"><?php $L->p('Save') ?></button> - <a class="btn btn-secondary btn-sm" href="<?php echo HTML_PATH_ADMIN_ROOT.'plugins' ?>" role="button"><?php $L->p('Cancel') ?></a> + // ============================================================================ + // Functions for the view + // ============================================================================ + function changePluginsPosition() { + $("li.list-group-item").each(function(index, value) { + var args = { + position: index, + className: $(this).data("class-name") + }; + console.log(index); + api.configurePlugin(args).then(function(response) { + if (response.status == 0) { + logs('Plugin configured: ' + response.data.key); + } else { + logs('An error occurred while trying to configured the plugin.'); + showAlertError(response.message); + } + }); + }); + + showAlertInfo("<?php $L->p('The changes have been saved') ?>"); + } + + // ============================================================================ + // Events for the view + // ============================================================================ + $(document).ready(function() { + $("#btnSave").on("click", function() { + changePluginsPosition(); + }); + }); + + // ============================================================================ + // Initlization for the view + // ============================================================================ + $(document).ready(function() { + $('.list-group-sortable').sortable({ + placeholderClass: 'list-group-item' + }); + }); +</script> + +<div class="d-flex align-items-center mb-4"> + <h2 class="m-0"><i class="bi bi-arrow-down-up"></i><?php $L->p('Plugins position') ?></h2> + <div class="ms-auto"> + <button id="btnSave" type="button" class="btn btn-primary btn-sm"><?php $L->p('Save') ?></button> + <a id="btnCancel" class="btn btn-secondary btn-sm" href="<?php echo HTML_PATH_ADMIN_ROOT . 'plugins' ?>" role="button"><?php $L->p('Cancel') ?></a> </div> - <?php echo Bootstrap::pageTitle(array('title'=>$L->g('Plugins position'), 'icon'=>'tags')); ?> </div> -<div class="alert alert-primary"><?php $L->p('Drag and Drop to sort the plugins') ?></div> +<div class="alert alert-primary"> + <?php $L->p('Drag and Drop to sort the plugins') ?> +</div> -<?php - // Token CSRF - echo Bootstrap::formInputHidden(array( - 'name'=>'tokenCSRF', - 'value'=>$security->getTokenCSRF() - )); +<?php echo Bootstrap::formTitle(array('title' => $L->g('Website plugins'))) ?> - echo Bootstrap::formInputHidden(array( - 'name'=>'plugin-list', - 'value'=>'' - )); +<ul class="website-plugins list-group list-group-sortable"> +<?php foreach ($plugins['siteSidebar'] as $plugin): ?> + <li class="list-group-item" data-class-name="<?php echo $plugin->className() ?>"> + <i class="bi bi-arrows-expand"></i><?php echo $plugin->name() ?> + </li> +<?php endforeach; ?> +</ul> - echo '<ul class="list-group list-group-sortable">'; - foreach ($plugins['siteSidebar'] as $Plugin) { - echo '<li class="list-group-item" data-plugin="'.$Plugin->className().'"><span class="bi-arrows-v"></span> '.$Plugin->name().'</li>'; - } - echo '</ul>'; -?> +<?php echo Bootstrap::formTitle(array('title' => $L->g('Dashboard plugins'))) ?> -<?php echo Bootstrap::formClose(); ?> - -<script> -$(document).ready(function() { - $('.list-group-sortable').sortable({ - placeholderClass: 'list-group-item' - }); - - $(".jsbuttonSave").on("click", function() { - var tmp = []; - $("li.list-group-item").each(function() { - tmp.push( $(this).attr("data-plugin") ); - }); - $("#jsplugin-list").attr("value", tmp.join(",") ); - $("#jsform").submit(); - }); -}); -</script> \ No newline at end of file +<ul class="dashboard-plugins list-group list-group-sortable"> +<?php foreach ($plugins['dashboard'] as $plugin): ?> + <li class="list-group-item" data-class-name="<?php echo $plugin->className() ?>"> + <i class="bi bi-arrows-expand"></i><?php echo $plugin->name() ?> + </li> +<?php endforeach; ?> +</ul> \ No newline at end of file diff --git a/bl-kernel/admin/views/plugins-settings.php b/bl-kernel/admin/views/plugins-settings.php index 2c377e26..beaecf63 100644 --- a/bl-kernel/admin/views/plugins-settings.php +++ b/bl-kernel/admin/views/plugins-settings.php @@ -9,11 +9,42 @@ // Functions for the view // ============================================================================ + function configurePlugin(className) { + var args = { + className: className + }; + + $('input').each(function() { + var key = $(this).attr('name'); + var value = $(this).val(); + args[key] = value; + }); + + $('select').each(function() { + var key = $(this).attr('name'); + var value = $(this).val(); + args[key] = value; + }); + + api.configurePlugin(args).then(function(response) { + if (response.status == 0) { + logs('Plugin configured: ' + response.data.key); + showAlertInfo("<?php $L->p('The changes have been saved') ?>"); + } else { + logs('An error occurred while trying to configured the plugin.'); + showAlertError(response.message); + } + }); + } + // ============================================================================ // Events for the view // ============================================================================ $(document).ready(function() { - // No events for the view yet + $('#btnSave').on('click', function() { + var className = $(this).data('class-name'); + configurePlugin(className); + }); }); // ============================================================================ @@ -24,29 +55,20 @@ }); </script> -<?php echo Bootstrap::formOpen(array('name' => 'pluginSettings')); ?> - -<div class="d-flex align-items-center mb-3"> +<div class="d-flex align-items-center mb-4"> <h2 class="m-0"><i class="bi bi-node-plus"></i><?php echo $plugin->name() ?></h2> <?php if ($plugin->formButtons()) : ?> <div class="ms-auto"> - <button type="submit" class="btn btn-primary btn-sm" name="save"><?php $L->p('Save') ?></button> - <a class="btn btn-secondary btn-sm" href="<?php echo HTML_PATH_ADMIN_ROOT . 'plugins' ?>" role="button"><?php $L->p('Cancel') ?></a> + <button id="btnSave" type="button" class="btn btn-primary btn-sm" data-class-name="<?php echo $plugin->className() ?>"><?php $L->p('Save') ?></button> + <a id="btnCancel" class="btn btn-secondary btn-sm" href="<?php echo HTML_PATH_ADMIN_ROOT . 'plugins' ?>" role="button"><?php $L->p('Cancel') ?></a> </div> <?php endif; ?> </div> <?php - echo Bootstrap::formInputHidden(array( - 'name' => 'tokenCSRF', - 'value' => $security->getTokenCSRF() - )); - if ($plugin->description()) { echo '<div class="alert alert-primary" role="alert">'.$plugin->description().'</div>'; } echo $plugin->form(); ?> - -<?php echo Bootstrap::formClose(); ?> \ No newline at end of file diff --git a/bl-kernel/admin/views/plugins.php b/bl-kernel/admin/views/plugins.php index 61509a97..9139662a 100644 --- a/bl-kernel/admin/views/plugins.php +++ b/bl-kernel/admin/views/plugins.php @@ -9,9 +9,9 @@ // Functions for the view // ============================================================================ - function activatePlugin(pluginClassName) { + function activatePlugin(className) { var args = { - pluginClassName: pluginClassName + className: className }; api.activatePlugin(args).then(function(response) { if (response.status == 0) { @@ -24,9 +24,9 @@ }); } - function deactivatePlugin(pluginClassName) { + function deactivatePlugin(className) { var args = { - pluginClassName: pluginClassName + className: className }; api.deactivatePlugin(args).then(function(response) { if (response.status == 0) { @@ -59,13 +59,13 @@ }); $('.activatePlugin').on('click', function() { - var pluginClassName = $(this).data('class-name'); - activatePlugin(pluginClassName); + var className = $(this).data('class-name'); + activatePlugin(className); }); $('.deactivatePlugin').on('click', function() { - var pluginClassName = $(this).data('class-name'); - deactivatePlugin(pluginClassName); + var className = $(this).data('class-name'); + deactivatePlugin(className); }); }); diff --git a/bl-kernel/boot/rules/60.plugins.php b/bl-kernel/boot/rules/60.plugins.php index 11d67fba..5d4d61ea 100644 --- a/bl-kernel/boot/rules/60.plugins.php +++ b/bl-kernel/boot/rules/60.plugins.php @@ -129,6 +129,12 @@ function buildPlugins() return $a->position()>$b->position(); } ); + + // Sort the plugins by the position for the dashboard + uasort($plugins['dashboard'], function ($a, $b) { + return $a->position()>$b->position(); + } + ); } } diff --git a/bl-kernel/functions.php b/bl-kernel/functions.php index e553cf5b..c2aba446 100644 --- a/bl-kernel/functions.php +++ b/bl-kernel/functions.php @@ -600,19 +600,19 @@ function uploadPageFile($pageKey) { /* Install and activate a plugin === Bludit v4 - @pluginClassName string The plugin PHP class name + @className string The plugin PHP class name @return string/bool Returns TRUE on successful install, FALSE otherwise */ -function activatePlugin($pluginClassName) { +function activatePlugin($className) { global $plugins; global $syslog; - if (!isset($plugins['all'][$pluginClassName])) { - Log::set(__FUNCTION__.LOG_SEP.'The plugin doesn\'t exist: '.$pluginClassName, LOG_TYPE_ERROR); + if (!isset($plugins['all'][$className])) { + Log::set(__FUNCTION__.LOG_SEP.'The plugin doesn\'t exist: '.$className, LOG_TYPE_ERROR); return false; } - $plugin = $plugins['all'][$pluginClassName]; + $plugin = $plugins['all'][$className]; if ($plugin->install()) { $syslog->add(array( 'dictionaryKey'=>'plugin-activated', @@ -628,19 +628,19 @@ function activatePlugin($pluginClassName) { /* Uninstall and deactivate a plugin === Bludit v4 - @pluginClassName string The plugin PHP class name + @className string The plugin PHP class name @return string/bool Returns TRUE on successful install, FALSE otherwise */ -function deactivatePlugin($pluginClassName) { +function deactivatePlugin($className) { global $plugins; global $syslog; - if (!isset($plugins['all'][$pluginClassName])) { - Log::set(__FUNCTION__.LOG_SEP.'The plugin doesn\'t exist: '.$pluginClassName, LOG_TYPE_ERROR); + if (!isset($plugins['all'][$className])) { + Log::set(__FUNCTION__.LOG_SEP.'The plugin doesn\'t exist: '.$className, LOG_TYPE_ERROR); return false; } - $plugin = $plugins['all'][$pluginClassName]; + $plugin = $plugins['all'][$className]; if ($plugin->uninstall()) { $syslog->add(array( 'dictionaryKey'=>'plugin-deactivated', @@ -654,6 +654,34 @@ function deactivatePlugin($pluginClassName) { return false; } +/* Change plugins settings === Bludit v4 + + @args array The array $args supports all the keys from the plugin database + @return bool Returns TRUE on successful configure, FALSE otherwise +*/ +function configurePlugin($args) { + global $plugins; + global $syslog; + + // Plugin class name + $className = $args['className']; + + // Check if the plugin exists + if (!isset($plugins['all'][$className])) { + Log::set(__FUNCTION__.LOG_SEP.'The plugin doesn\'t exist: '.$className, LOG_TYPE_ERROR); + return false; + } + + $plugin = $plugins['all'][$className]; + $plugin->configure($args); + $syslog->add(array( + 'dictionaryKey'=>'plugin-configured', + 'notes'=>$plugin->name() + )); + Log::set(__FUNCTION__.LOG_SEP.'Plugin configured: '.$className, LOG_TYPE_INFO); + return true; +} + // Re-index database of categories // If you create/edit/remove a page is necessary regenerate the database of categories function reindexCategories() { @@ -878,27 +906,7 @@ function deactivateAllPlugin() { return false; } -function changePluginsPosition($pluginClassList) { - global $plugins; - global $syslog; - global $L; - foreach ($pluginClassList as $position=>$pluginClassName) { - if (isset($plugins['all'][$pluginClassName])) { - $plugin = $plugins['all'][$pluginClassName]; - $plugin->setPosition(++$position); - } - } - - // Add to syslog - $syslog->add(array( - 'dictionaryKey'=>'plugins-sorted', - 'notes'=>'' - )); - - Alert::set($L->g('The changes have been saved')); - return true; -} // Execute the plugins by hook function execPluginsByHook($hook, $args = array()) { diff --git a/bl-kernel/helpers/html.class.php b/bl-kernel/helpers/html.class.php index eb2160a7..4d6cd376 100644 --- a/bl-kernel/helpers/html.class.php +++ b/bl-kernel/helpers/html.class.php @@ -48,28 +48,32 @@ class HTML { public static function jquery() { + // https://jquery.com/ return '<script src="'.DOMAIN_CORE_VENDORS.'jquery/jquery.min.js?version='.BLUDIT_VERSION.'"></script>'.PHP_EOL; } public static function jsBootstrap($attributes='') { + // https://getbootstrap.com/ return '<script '.$attributes.' src="'.DOMAIN_CORE_VENDORS.'bootstrap/bootstrap.bundle.min.js?version='.BLUDIT_VERSION.'"></script>'.PHP_EOL; } public static function cssBootstrap() { + // https://getbootstrap.com/ return '<link rel="stylesheet" type="text/css" href="'.DOMAIN_CORE_VENDORS.'bootstrap/bootstrap.min.css?version='.BLUDIT_VERSION.'">'.PHP_EOL; } public static function cssBootstrapIcons() { + // https://icons.getbootstrap.com/ return '<link rel="stylesheet" type="text/css" href="'.DOMAIN_CORE_VENDORS.'bootstrap-icons/bootstrap-icons.css?version='.BLUDIT_VERSION.'">'.PHP_EOL; } public static function jsSortable($attributes='') { // https://github.com/psfpro/bootstrap-html5sortable - return '<script '.$attributes.' src="'.DOMAIN_CORE_JS.'jquery.sortable.min.js?version='.BLUDIT_VERSION.'"></script>'.PHP_EOL; + return '<script '.$attributes.' src="'.DOMAIN_CORE_VENDORS.'bootstrap-html5sortable/jquery.sortable.min.js?version='.BLUDIT_VERSION.'"></script>'.PHP_EOL; } } diff --git a/bl-kernel/js/api.js b/bl-kernel/js/api.js index fd9c6c60..ba2d07df 100644 --- a/bl-kernel/js/api.js +++ b/bl-kernel/js/api.js @@ -321,7 +321,7 @@ class API { @return string */ async activatePlugin(args) { - var url = this.apiURL + "plugins/" + args['pluginClassName']; + var url = this.apiURL + "plugins/" + args['className']; var body = Object.assign({}, this.body, args); try { var response = await fetch(url, { @@ -340,13 +340,13 @@ class API { } } - /* Uninstall and deactivate a plugin === Bludit v4 + /* Deactivate and uninstall a plugin === Bludit v4 @args array @return string */ async deactivatePlugin(args) { - var url = this.apiURL + "plugins/" + args['pluginClassName']; + var url = this.apiURL + "plugins/" + args['className']; var body = Object.assign({}, this.body, args); try { var response = await fetch(url, { @@ -365,4 +365,29 @@ class API { } } + /* Configure a plugin + + @args array Arguments can be any of the fields from the plugin database + @return string The plugin class name + */ + async configurePlugin(args) { + var url = this.apiURL + "plugins/" + args['className']; + var body = Object.assign({}, this.body, args); + try { + var response = await fetch(url, { + credentials: "same-origin", + method: "PUT", + body: JSON.stringify(body), + headers: new Headers({ + "Content-Type": "application/json" + }) + }); + var json = await response.json(); + return json; + } catch (err) { + console.log(err); + return true; + } + } + } \ No newline at end of file diff --git a/bl-kernel/js/jquery.sortable.min.js b/bl-kernel/vendors/bootstrap-html5sortable/jquery.sortable.min.js similarity index 100% rename from bl-kernel/js/jquery.sortable.min.js rename to bl-kernel/vendors/bootstrap-html5sortable/jquery.sortable.min.js diff --git a/bl-languages/en.json b/bl-languages/en.json index 6f2f21b5..76466321 100644 --- a/bl-languages/en.json +++ b/bl-languages/en.json @@ -397,5 +397,7 @@ "are-you-sure-you-want-to-delete-this-user": "Are you sure you want to delete this user?", "are-you-sure-you-want-to-delete-this-page": "Are you sure you want to delete this page?", "are-you-sure-you-want-to-delete-this-category?": "Are you sure you want to delete this category?", - "are-you-sure-you-want-to-change-the-password?": "Are you sure you want to change the password?" + "are-you-sure-you-want-to-change-the-password?": "Are you sure you want to change the password?", + "website-plugins": "Website plugins", + "dashboard-plugins": "Dashboard plugins" } \ No newline at end of file diff --git a/bl-plugins/api/plugin.php b/bl-plugins/api/plugin.php index b6b33e7e..91268b75 100644 --- a/bl-plugins/api/plugin.php +++ b/bl-plugins/api/plugin.php @@ -283,6 +283,11 @@ class pluginAPI extends Plugin { $pluginClassName = $parmB; $data = $this->deactivatePlugin($pluginClassName); } + // (PUT) /api/plugins/:key + elseif ( ($method==='PUT') && ($parmA==='plugins') && !empty($parmB) ) { + $inputs['className'] = $parmB; + $data = $this->configurePlugin($inputs); + } // (GET) /api/helper/:name elseif ( ($method==='GET') && ($parmA==='helper') && !empty($parmB) ) { $name = $parmB; @@ -1009,4 +1014,24 @@ class pluginAPI extends Plugin { 'message'=>'An error occurred while trying to uninstall the plugin.' ); } + + + /* Configure a plugin === Bludit v4 + Referer to the function configurePlugin() from functions.php + */ + private function configurePlugin($args) + { + if (configurePlugin($args)) { + return array( + 'status'=>'0', + 'message'=>'Plugin configured.', + 'data'=>array('key'=>$args['className']) + ); + } + + return array( + 'status'=>'1', + 'message'=>'An error occurred while trying to configure the plugin.' + ); + } } \ No newline at end of file diff --git a/bl-plugins/visits-stats/plugin.php b/bl-plugins/visits-stats/plugin.php index 69f1740b..d637d326 100644 --- a/bl-plugins/visits-stats/plugin.php +++ b/bl-plugins/visits-stats/plugin.php @@ -51,7 +51,7 @@ class pluginVisitsStats extends Plugin { $labelUnique = $L->g('Unique'); return <<<EOF - <div class="pluginVisitsStats"> + <div class="pluginVisitsStats mb-4"> <h3 class="m-0 p-0"><i class="bi bi-bar-chart"></i>$label</h3> <canvas id="visits-stats"></canvas> </div> diff --git a/bl-plugins/welcome/plugin.php b/bl-plugins/welcome/plugin.php index d0d42543..dbd9d50a 100644 --- a/bl-plugins/welcome/plugin.php +++ b/bl-plugins/welcome/plugin.php @@ -26,8 +26,8 @@ class pluginWelcome extends Plugin { $labelGoodNight = $L->g('good-night'); return <<<EOF - <div class="pluginWelcome"> - <h2 id="hello-message" class="m-0 p-0"><i class="bi bi-emoji-laughing"></i>Welcome</h3> + <div class="pluginWelcome mb-4"> + <h2 id="hello-message" class="m-0 p-0"><i class="bi bi-emoji-laughing"></i>Welcome</h2> </div> <script>