From b838050e5828b5cbf32b9e82ce11c9cc54592809 Mon Sep 17 00:00:00 2001 From: Piyush Mishra <me@piyushmishra.com> Date: Sat, 20 Aug 2011 19:11:52 +0530 Subject: [PATCH] added new plugins config cascade and added plugin.info.txt --- .gitignore | 1 + conf/plugins.protected.php | 6 + inc/config_cascade.php | 5 + inc/infoutils.php | 4 +- inc/lang/en/lang.php | 2 +- inc/plugincontroller.class.php | 167 ++++++++++++++++++++---- inc/pluginutils.php | 33 ++++- lib/plugins/acl/admin.php | 14 -- lib/plugins/acl/plugin.info.txt | 6 + lib/plugins/config/admin.php | 15 --- lib/plugins/config/plugin.info.txt | 6 + lib/plugins/info/plugin.info.txt | 6 + lib/plugins/revert/admin.php | 14 -- lib/plugins/revert/plugin.info.txt | 6 + lib/plugins/usermanager/admin.php | 14 -- lib/plugins/usermanager/plugin.info.txt | 6 + 16 files changed, 216 insertions(+), 89 deletions(-) create mode 100644 conf/plugins.protected.php create mode 100644 lib/plugins/acl/plugin.info.txt create mode 100644 lib/plugins/config/plugin.info.txt create mode 100644 lib/plugins/info/plugin.info.txt create mode 100644 lib/plugins/revert/plugin.info.txt create mode 100644 lib/plugins/usermanager/plugin.info.txt diff --git a/.gitignore b/.gitignore index 6ad14d206..f70efa665 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ /conf/words.aspell /conf/lang/* /conf/plugin_lang/* +/conf/plugins.local.* .htaccess *.swp *.bak diff --git a/conf/plugins.protected.php b/conf/plugins.protected.php new file mode 100644 index 000000000..bdfe821c5 --- /dev/null +++ b/conf/plugins.protected.php @@ -0,0 +1,6 @@ +<?php +$plugins['acl'] = 1; +$plugins['plugin'] = 1; +$plugins['config'] = 1; +$plugins['usermanager'] = 1; +$plugins['revert'] = 1; diff --git a/inc/config_cascade.php b/inc/config_cascade.php index 48ed5a000..c01778e99 100644 --- a/inc/config_cascade.php +++ b/inc/config_cascade.php @@ -64,6 +64,11 @@ $config_cascade = array_merge( 'plainauth.users' => array( 'default' => DOKU_CONF.'users.auth.php', ), + + 'plugins' => array( + 'local' => array(DOKU_CONF.'plugins.local.php'), + 'protected' => array(DOKU_CONF.'plugins.protected.php'), + ), ), $config_cascade ); diff --git a/inc/infoutils.php b/inc/infoutils.php index 786661d01..f1deec66b 100644 --- a/inc/infoutils.php +++ b/inc/infoutils.php @@ -66,8 +66,8 @@ function getVersionData(){ $chunk = fread($fh,2000); fclose($fh); $chunk = trim($chunk); - $chunk = array_pop(explode("\n",$chunk)); //last log line - $chunk = array_shift(explode("\t",$chunk)); //strip commit msg + $chunk = @array_pop(explode("\n",$chunk)); //last log line + $chunk = @array_shift(explode("\t",$chunk)); //strip commit msg $chunk = explode(" ",$chunk); array_pop($chunk); //strip timezone $date = date('Y-m-d',array_pop($chunk)); diff --git a/inc/lang/en/lang.php b/inc/lang/en/lang.php index 95356f7b4..02dff5cb7 100644 --- a/inc/lang/en/lang.php +++ b/inc/lang/en/lang.php @@ -318,5 +318,5 @@ $lang['seconds'] = '%d seconds ago'; $lang['wordblock'] = 'Your change was not saved because it contains blocked text (spam).'; - +$lang['plugin_insterr'] = "Plugin installed incorrectly. Rename plugin directory '%s' to '%s'."; //Setup VIM: ex: et ts=2 : diff --git a/inc/plugincontroller.class.php b/inc/plugincontroller.class.php index ea5725d47..6dcdcdfff 100644 --- a/inc/plugincontroller.class.php +++ b/inc/plugincontroller.class.php @@ -11,11 +11,18 @@ if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); class Doku_Plugin_Controller { - var $list_enabled = array(); - var $list_disabled = array(); var $list_bytype = array(); + var $tmp_plugins = array(); + var $plugin_cascade = array('default'=>array(),'local'=>array(),'protected'=>array()); + var $last_local = ''; + //backup of tmp_plugins needed for write check + var $tmp_bak =array(); - function Doku_Plugin_Controller() { + /** + * Populates the master list of plugins + */ + function __construct() { + $this->loadConfig(); $this->_populateMasterList(); } @@ -37,7 +44,7 @@ class Doku_Plugin_Controller { // request the complete list if (!$type) { - return $all ? array_merge($this->list_enabled,$this->list_disabled) : $this->list_enabled; + return $all ? array_keys($this->tmp_plugins) : array_keys(array_filter($this->tmp_plugins)); } if (!isset($this->list_bytype[$type]['enabled'])) { @@ -61,9 +68,10 @@ class Doku_Plugin_Controller { * @param $disabled bool true to load even disabled plugins * @return objectreference the plugin object or null on failure */ - function &load($type,$name,$new=false,$disabled=false){ + function load($type,$name,$new=false,$disabled=false){ + //we keep all loaded plugins available in global scope for reuse - global $DOKU_PLUGINS; + global $DOKU_PLUGINS,$lang; list($plugin,$component) = $this->_splitName($name); @@ -85,12 +93,12 @@ class Doku_Plugin_Controller { //construct class and instantiate if (!class_exists($class, true)) { + # the plugin might be in the wrong directory $dir = $this->get_directory($plugin); $inf = confToHash(DOKU_PLUGIN."$dir/plugin.info.txt"); if($inf['base'] && $inf['base'] != $plugin){ - msg("Plugin installed incorrectly. Rename plugin directory '". - hsc($plugin)."' to '".hsc($inf['base'])."'.",-1); + msg(sprintf($lang['plugin_insterr'],hsc($plugin),hsc($inf['base'])),-1); } return null; } @@ -100,30 +108,27 @@ class Doku_Plugin_Controller { } function isdisabled($plugin) { - return (array_search($plugin, $this->list_enabled) === false); + return empty($this->tmp_plugins[$plugin]); } - function enable($plugin) { - if (array_search($plugin, $this->list_disabled) !== false) { - return @unlink(DOKU_PLUGIN.$plugin.'/disabled'); - } - return false; + function disable($plugin) { + if(array_key_exists($plugin,$this->plugin_cascade['protected'])) return false; + $this->tmp_plugins[$plugin] = 0; + return $this->saveList(); } - function disable($plugin) { - if (array_search($plugin, $this->list_enabled) !== false) { - return @touch(DOKU_PLUGIN.$plugin.'/disabled'); - } - return false; + function enable($plugin) { + if(array_key_exists($plugin,$this->plugin_cascade['protected'])) return false; + $this->tmp_plugins[$plugin] = 1; + return $this->saveList(); } function get_directory($plugin) { return $plugin; } - function _populateMasterList() { - global $conf; - if ($dh = opendir(DOKU_PLUGIN)) { + protected function _populateMasterList() { + if ($dh = @opendir(DOKU_PLUGIN)) { while (false !== ($plugin = readdir($dh))) { if ($plugin[0] == '.') continue; // skip hidden entries if (is_file(DOKU_PLUGIN.$plugin)) continue; // skip files, we're only interested in directories @@ -132,19 +137,123 @@ class Doku_Plugin_Controller { // the plugin was disabled by rc2009-01-26 // disabling mechanism was changed back very soon again // to keep everything simple we just skip the plugin completely - }elseif(@file_exists(DOKU_PLUGIN.$plugin.'/disabled') || + }elseif(@file_exists(DOKU_PLUGIN.$plugin.'/disabled')) { + if(empty($this->plugin_cascade['local'][$plugin])) + $all_plugins[$plugin] = 0; + else + $all_plugins[$plugin] = 1; + //treat this as a default disabled plugin(over-rideable by the plugin manager) + $this->plugin_cascade['default'][$plugin] = 0; + //TODO take this out before final release, + //it is here only for other developers to be able to switch branches easily + //@unlink(DOKU_PLUGIN.$plugin.'/disabled'); + continue; + } + elseif((array_key_exists($plugin,$this->tmp_plugins) && $this->tmp_plugins[$plugin] == 0) || ($plugin === 'plugin' && isset($conf['pluginmanager']) && !$conf['pluginmanager'])){ - $this->list_disabled[] = $plugin; + $all_plugins[$plugin] = 0; + } elseif((array_key_exists($plugin,$this->tmp_plugins) && $this->tmp_plugins[$plugin] == 1)) { + $all_plugins[$plugin] = 1; } else { - $this->list_enabled[] = $plugin; + $all_plugins[$plugin] = 1; } } + $this->tmp_plugins = $all_plugins; + $this->saveList(); } } + protected function checkRequire($files) { + $plugins = array(); + foreach($files as $file) { + if(file_exists($file)) { + @include_once($file); + } + } + return $plugins; + } + + function getCascade() { + return $this->plugin_cascade; + } + /** + * Save the current list of plugins + */ + function saveList() { + if(!empty($this->tmp_plugins)) { + //quick check to ensure rewrite is necessary + if($this->tmp_plugins != $this->tmp_bak) { + //Rebuild local for better check and saving + $local_plugins = $this->rebuildLocal(); + //only write if the list has changed + if($local_plugins != $this->plugin_cascade['local']) { + $file = $this->last_local; + $out = "<?php\n"; + foreach ($local_plugins as $plugin => $value) { + $out .= "\$plugins['$plugin'] = $value;\n"; + } + // backup current file (remove any existing backup) + if (@file_exists($file)) { + if (@file_exists($file.'.bak')) @unlink($file.'.bak'); + if (!io_rename($file, $file.'.bak')) return false; + } + //check if can open for writing, else restore + if (!$fh = @fopen($file, 'wb')) { + io_rename($file.'.bak', $file);// problem opening, restore the backup + return false; + } + @fwrite($fh, $out); + fclose($fh); + return true; + } + } + } + return false; + } + + /** + * Rebuild the set of local plugins + * @return array array of plugins to be saved in end($config_cascade['plugins']['local']) + */ + function rebuildLocal() { + //assign to local variable to avoid overwriting + $backup = $this->tmp_plugins; + //Can't do anything about protected one so rule them out completely + $local_default = array_diff_key($backup,$this->plugin_cascade['protected']); + //Diff between local+default and default + //gives us the ones we need to check and save + $diffed_ones = array_diff_key($local_default,$this->plugin_cascade['default']); + //The ones which we are sure of (list of 0s not in default) + $sure_plugins = array_filter($diffed_ones,array($this,'negate')); + //the ones in need of diff + $conflicts = array_diff_key($local_default,$diffed_ones); + //The final list + return array_merge($sure_plugins,array_diff_assoc($conflicts,$this->plugin_cascade['default'])); + } + + /** + * Build the list of plugins and cascade + * + */ + function loadConfig() { + global $config_cascade; + foreach(array('default','protected') as $type) { + if(array_key_exists($type,$config_cascade['plugins'])) + $this->plugin_cascade[$type] = $this->checkRequire($config_cascade['plugins'][$type]); + } + $local = $config_cascade['plugins']['local']; + $this->last_local = array_pop($local); + $this->plugin_cascade['local'] = $this->checkRequire(array($this->last_local)); + if(is_array($local)) { + $this->plugin_cascade['default'] = array_merge($this->plugin_cascade['default'],$this->checkRequire($local)); + } + $this->tmp_plugins = array_merge($this->plugin_cascade['default'],$this->plugin_cascade['local'],$this->plugin_cascade['protected']); + $this->tmp_bak = $this->tmp_plugins; + } + function _getListByType($type, $enabled) { - $master_list = $enabled ? $this->list_enabled : $this->list_disabled; + $master_list = $enabled ? array_keys(array_filter($this->tmp_plugins)) : array_keys(array_filter($this->tmp_plugins,array($this,'negate'))); $plugins = array(); foreach ($master_list as $plugin) { @@ -169,11 +278,13 @@ class Doku_Plugin_Controller { } function _splitName($name) { - if (array_search($name, $this->list_enabled + $this->list_disabled) === false) { + if (array_search($name, array_keys($this->tmp_plugins)) === false) { return explode('_',$name,2); } return array($name,''); } - + function negate($input) { + return !(bool) $input; + } } diff --git a/inc/pluginutils.php b/inc/pluginutils.php index 85bcaee1e..897020a6c 100644 --- a/inc/pluginutils.php +++ b/inc/pluginutils.php @@ -16,7 +16,7 @@ function plugin_list($type='',$all=false) { global $plugin_controller; return $plugin_controller->getList($type,$all); } -function &plugin_load($type,$name,$new=false,$disabled=false) { +function plugin_load($type,$name,$new=false,$disabled=false) { global $plugin_controller; return $plugin_controller->load($type,$name,$new,$disabled); } @@ -36,3 +36,34 @@ function plugin_directory($plugin) { global $plugin_controller; return $plugin_controller->get_directory($plugin); } +function plugin_getcascade() { + global $plugin_controller; + return $plugin_controller->getCascade(); +} +/** + * return a list (name & type) of all the component plugins that make up this plugin + * + */ +function get_plugin_components($plugin) { + global $plugin_types; + static $plugins; + if(empty($plugins[$plugin])) { + $components = array(); + $path = DOKU_PLUGIN.plugin_directory($plugin).'/'; + + foreach ($plugin_types as $type) { + if (@file_exists($path.$type.'.php')) { $components[] = array('name'=>$plugin, 'type'=>$type); continue; } + + if ($dh = @opendir($path.$type.'/')) { + while (false !== ($cp = readdir($dh))) { + if ($cp == '.' || $cp == '..' || strtolower(substr($cp,-4)) != '.php') continue; + + $components[] = array('name'=>$plugin.'_'.substr($cp, 0, -4), 'type'=>$type); + } + closedir($dh); + } + } + $plugins[$plugin] = $components; + } + return $plugins[$plugin]; +} diff --git a/lib/plugins/acl/admin.php b/lib/plugins/acl/admin.php index 53f6db0cc..a6b0624bc 100644 --- a/lib/plugins/acl/admin.php +++ b/lib/plugins/acl/admin.php @@ -30,20 +30,6 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin { var $usersgroups = array(); var $specials = array(); - /** - * return some info - */ - function getInfo(){ - return array( - 'author' => 'Andreas Gohr', - 'email' => 'andi@splitbrain.org', - 'date' => '2011-04-16', - 'name' => 'ACL Manager', - 'desc' => 'Manage Page Access Control Lists', - 'url' => 'http://dokuwiki.org/plugin:acl', - ); - } - /** * return prompt for admin menu */ diff --git a/lib/plugins/acl/plugin.info.txt b/lib/plugins/acl/plugin.info.txt new file mode 100644 index 000000000..f108a2390 --- /dev/null +++ b/lib/plugins/acl/plugin.info.txt @@ -0,0 +1,6 @@ +author Andreas Gohr +email andi@splitbrain.org +date 2011-04-16 +name ACL Manager +desc Manage Page Access Control Lists +url http://dokuwiki.org/plugin:acl diff --git a/lib/plugins/config/admin.php b/lib/plugins/config/admin.php index e24f3b87b..64906171d 100644 --- a/lib/plugins/config/admin.php +++ b/lib/plugins/config/admin.php @@ -32,21 +32,6 @@ class admin_plugin_config extends DokuWiki_Admin_Plugin { var $_session_started = false; var $_localised_prompts = false; - /** - * return some info - */ - function getInfo(){ - - return array( - 'author' => 'Christopher Smith', - 'email' => 'chris@jalakai.co.uk', - 'date' => '2007-08-05', - 'name' => 'Configuration Manager', - 'desc' => "Manage Dokuwiki's Configuration Settings", - 'url' => 'http://dokuwiki.org/plugin:config', - ); - } - function getMenuSort() { return 100; } /** diff --git a/lib/plugins/config/plugin.info.txt b/lib/plugins/config/plugin.info.txt new file mode 100644 index 000000000..ace4889b6 --- /dev/null +++ b/lib/plugins/config/plugin.info.txt @@ -0,0 +1,6 @@ +author Christopher Smith +email chris@jalakai.co.uk +date 2007-08-05 +name Configuration Manager +desc Manage Dokuwiki's Configuration Settings +url http://dokuwiki.org/plugin:config diff --git a/lib/plugins/info/plugin.info.txt b/lib/plugins/info/plugin.info.txt new file mode 100644 index 000000000..2432225f1 --- /dev/null +++ b/lib/plugins/info/plugin.info.txt @@ -0,0 +1,6 @@ +author Andreas Gohr +email andi@splitbrain.org +date 2008-09-12 +name Info Plugin +desc Displays information about various DokuWiki internals +url http://dokuwiki.org/plugin:info diff --git a/lib/plugins/revert/admin.php b/lib/plugins/revert/admin.php index e188e2488..2aaf1395f 100644 --- a/lib/plugins/revert/admin.php +++ b/lib/plugins/revert/admin.php @@ -20,20 +20,6 @@ class admin_plugin_revert extends DokuWiki_Admin_Plugin { $this->setupLocale(); } - /** - * return some info - */ - function getInfo(){ - return array( - 'author' => 'Andreas Gohr', - 'email' => 'andi@splitbrain.org', - 'date' => '2008-12-10', - 'name' => 'Revert Manager', - 'desc' => 'Allows you to mass revert recent edits', - 'url' => 'http://dokuwiki.org/plugin:revert', - ); - } - /** * access for managers */ diff --git a/lib/plugins/revert/plugin.info.txt b/lib/plugins/revert/plugin.info.txt new file mode 100644 index 000000000..5bb6f3413 --- /dev/null +++ b/lib/plugins/revert/plugin.info.txt @@ -0,0 +1,6 @@ +author Andreas Gohr +email andi@splitbrain.org +date 2008-12-10 +name Revert Manager +desc Allows you to mass revert recent edits +url http://dokuwiki.org/plugin:revert diff --git a/lib/plugins/usermanager/admin.php b/lib/plugins/usermanager/admin.php index e40ee9b7e..8e90be093 100644 --- a/lib/plugins/usermanager/admin.php +++ b/lib/plugins/usermanager/admin.php @@ -51,20 +51,6 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin { } } - /** - * return some info - */ - function getInfo(){ - - return array( - 'author' => 'Chris Smith', - 'email' => 'chris@jalakai.co.uk', - 'date' => '2008-09-17', - 'name' => 'User Manager', - 'desc' => 'Manage users '.$this->disabled, - 'url' => 'http://dokuwiki.org/plugin:usermanager', - ); - } /** * return prompt for admin menu */ diff --git a/lib/plugins/usermanager/plugin.info.txt b/lib/plugins/usermanager/plugin.info.txt new file mode 100644 index 000000000..7ec5fafd5 --- /dev/null +++ b/lib/plugins/usermanager/plugin.info.txt @@ -0,0 +1,6 @@ +author Chris Smith +email chris@jalakai.co.uk +date 2008-09-17 +name User Manager +desc Manage users +url http://dokuwiki.org/plugin:usermanager -- GitLab