Skip to content

Commit

Permalink
Fixes #378 - Plugin administration UI.
Browse files Browse the repository at this point in the history
  • Loading branch information
ArthurHoaro committed Jan 31, 2016
1 parent 423e2a8 commit a9c3aae
Show file tree
Hide file tree
Showing 20 changed files with 627 additions and 7 deletions.
114 changes: 114 additions & 0 deletions application/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,106 @@ function writeConfig($config, $isLoggedIn)
}
}

/**
* Process plugin administration form data and save it in an array.
*
* @param $formData
*
* @return array
*
* @throws PluginConfigOrderException
*/
function save_plugin_config($formData)
{
// Make sure there are no duplicates in orders.
if (!validate_plugin_order($formData)) {
throw new PluginConfigOrderException();
}

$plugins = array();
$newEnabledPlugins = array();
foreach ($formData as $key => $data) {
if (startsWith($key, 'order')) {
continue;
}

// If there is no order, it means a disabled plugin has been enabled.
if (isset($formData['order_' . $key])) {
$plugins[(int) $formData['order_' . $key]] = $key;
}
else {
$newEnabledPlugins[] = $key;
}
}

// New enabled plugins will be added at the end of order.
$plugins = array_merge($plugins, $newEnabledPlugins);

// Sort plugins by order.
if (!ksort($plugins)) {
throw new PluginConfigOrderException();
}

$finalPlugins = array();
// Make plugins order continuous.
foreach ($plugins as $plugin) {
$finalPlugins[] = $plugin;
}

return $finalPlugins;
}

/**
* Validate plugin array submitted.
* Will fail if there is duplicate orders value.
*
* @param array $formData Data from submitted form.
*
* @return bool true if ok, false otherwise.
*/
function validate_plugin_order($formData)
{
$orders = array();
foreach ($formData as $key => $value) {
// No duplicate order allowed.
if (in_array($value, $orders)) {
return false;
}

if (startsWith($key, 'order')) {
$orders[] = $value;
}
}

return true;
}

/**
* Affect plugin parameters values into plugins array.
*
* @param mixed $plugins Plugins array ($plugins[<plugin_name>]['parameters']['param_name'] = <value>.
* @param mixed $config Plugins configuration.
*
* @return mixed Updated $plugins array.
*/
function load_plugin_parameter_values($plugins, $config)
{
$out = $plugins;
foreach ($plugins as $name => $plugin) {
if (empty($plugin['parameters'])) {
continue;
}

foreach ($plugin['parameters'] as $key => $param) {
if (!empty($config[$key])) {
$out[$name]['parameters'][$key] = $config[$key];
}
}
}

return $out;
}

/**
* Milestone 0.9 - shaarli/Shaarli#41: options.php is not supported anymore.
* ==> if user is loggedIn, merge its content with config.php, then delete options.php.
Expand Down Expand Up @@ -132,3 +232,17 @@ public function __construct()
$this->message = 'You are not authorized to alter config.';
}
}

/**
* Exception used if an error occur while saving plugin configuration.
*/
class PluginConfigOrderException extends Exception
{
/**
* Construct exception.
*/
public function __construct()
{
$this->message = 'An error occurred while trying to save plugins loading order.';
}
}
43 changes: 43 additions & 0 deletions application/PluginManager.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

define('META_EXT', 'meta');

/**
* Class PluginManager
*
Expand Down Expand Up @@ -162,6 +164,47 @@ public function buildHookName($hook, $pluginName)
{
return 'hook_' . $pluginName . '_' . $hook;
}

/**
* Retrieve plugins metadata from *.meta (INI) files into an array.
* Metadata contains:
* - plugin description [description]
* - parameters split with ';' [parameters]
*
* Respects plugins order from settings.
*
* @return array plugins metadata.
*/
public function getPluginsMeta()
{
$metaData = array();
$dirs = glob(self::$PLUGINS_PATH . '/*', GLOB_ONLYDIR | GLOB_MARK);

// Browse all plugin directories.
foreach ($dirs as $pluginDir) {
$plugin = basename($pluginDir);
$metaFile = $pluginDir . $plugin . '.' . META_EXT;
if (!is_file($metaFile) || !is_readable($metaFile)) {
continue;
}

$metaData[$plugin] = parse_ini_file($metaFile);
$metaData[$plugin]['order'] = array_search($plugin, $this->authorizedPlugins);

// Read parameters and format them into an array.
$params = explode(';', $metaData[$plugin]['parameters']);
$metaData[$plugin]['parameters'] = array();
foreach ($params as $param) {
if (empty($param)) {
continue;
}

$metaData[$plugin]['parameters'][$param] = '';
}
}

return $metaData;
}
}

/**
Expand Down
12 changes: 12 additions & 0 deletions application/Router.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ class Router

public static $PAGE_LINKLIST = 'linklist';

public static $PAGE_PLUGINSADMIN = 'pluginadmin';

public static $PAGE_SAVE_PLUGINSADMIN = 'save_pluginadmin';

/**
* Reproducing renderPage() if hell, to avoid regression.
*
Expand Down Expand Up @@ -112,6 +116,14 @@ public static function findPage($query, $get, $loggedIn)
return self::$PAGE_IMPORT;
}

if (startswith($query, 'do='. self::$PAGE_PLUGINSADMIN)) {
return self::$PAGE_PLUGINSADMIN;
}

if (startswith($query, 'do='. self::$PAGE_SAVE_PLUGINSADMIN)) {
return self::$PAGE_SAVE_PLUGINSADMIN;
}

return self::$PAGE_LINKLIST;
}
}
67 changes: 67 additions & 0 deletions inc/plugin_admin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/**
* Change the position counter of a row.
*
* @param elem Element Node to change.
* @param toPos int New position.
*/
function changePos(elem, toPos)
{
var elemName = elem.getAttribute('data-line')

elem.setAttribute('data-order', toPos);
var hiddenInput = document.querySelector('[name="order_'+ elemName +'"]');
hiddenInput.setAttribute('value', toPos);
}

/**
* Move a row up or down.
*
* @param pos Element Node to move.
* @param move int Move: +1 (down) or -1 (up)
*/
function changeOrder(pos, move)
{
var newpos = parseInt(pos) + move;
var line = document.querySelector('[data-order="'+ pos +'"]');
var changeline = document.querySelector('[data-order="'+ newpos +'"]');
var parent = changeline.parentNode;

changePos(line, newpos);
changePos(changeline, parseInt(pos));
var changeItem = move < 0 ? changeline : changeline.nextSibling;
parent.insertBefore(line, changeItem);
}

/**
* Move a row up in the table.
*
* @param pos int row counter.
*
* @returns false
*/
function orderUp(pos)
{
if (pos == 0) {
return false;
}
changeOrder(pos, -1);
return false;
}

/**
* Move a down up in the table.
*
* @param pos int row counter.
*
* @returns false
*/
function orderDown(pos)
{
var lastpos = document.querySelector('[data-order]:last-child').getAttribute('data-order');
if (pos == lastpos) {
return false;
}

changeOrder(pos, +1);
return false;
}
64 changes: 64 additions & 0 deletions inc/shaarli.css
Original file line number Diff line number Diff line change
Expand Up @@ -1103,6 +1103,70 @@ ul.errors {
float: left;
}

#pluginsadmin {
width: 80%;
padding: 20px 0 0 20px;
}

#pluginsadmin section {
padding: 20px 0;
}

#pluginsadmin .plugin_parameters {
margin: 10px 0;
}

#pluginsadmin h1 {
font-style: normal;
}

#pluginsadmin h2 {
font-size: 1.4em;
font-weight: bold;
}

#pluginsadmin table {
width: 100%;
}

#pluginsadmin table, #pluginsadmin th, #pluginsadmin td {
border-width: 1px 0;
border-style: solid;
border-color: #c0c0c0;
}

#pluginsadmin table tr {

}

#pluginsadmin table th {
font-weight: bold;
padding: 10px 0;
}

#pluginsadmin table td {
padding: 5px 0;
}

#pluginsadmin input[type=submit] {
margin: 10px 0;
}

#pluginsadmin .plugin_parameter {
padding: 5px 0;
border-width: 1px 0;
border-style: solid;
border-color: #c0c0c0;
}

#pluginsadmin .float_label {
float: left;
width: 20%;
}

#pluginsadmin a {
color: black;
}
/* 404 page */
.error-container {

Expand Down
Loading

0 comments on commit a9c3aae

Please sign in to comment.