MDL-26943 implement subplugin support for local plugins

This commit is contained in:
Petr Škoda
2013-06-30 09:18:35 +02:00
parent 6a407a7c0e
commit 3601c5f09c
4 changed files with 95 additions and 28 deletions
+5 -4
View File
@@ -128,14 +128,15 @@ function uninstall_plugin($type, $name) {
// This may take a long time.
@set_time_limit(0);
// recursively uninstall all module/editor subplugins first
if ($type === 'mod' || $type === 'editor') {
$base = get_component_directory($type . '_' . $name);
// Recursively uninstall all subplugins first.
$subplugintypes = core_component::get_plugin_types_with_subplugins();
if (isset($subplugintypes[$type])) {
$base = core_component::get_plugin_directory($type, $name);
if (file_exists("$base/db/subplugins.php")) {
$subplugins = array();
include("$base/db/subplugins.php");
foreach ($subplugins as $subplugintype=>$dir) {
$instances = get_plugin_list($subplugintype);
$instances = core_component::get_plugin_list($subplugintype);
foreach ($instances as $subpluginname => $notusedpluginpath) {
uninstall_plugin($subplugintype, $subpluginname);
}
+71 -17
View File
@@ -29,7 +29,7 @@ class core_component {
/** @var array list of ignored directories - watch out for auth/db exception */
protected static $ignoreddirs = array('CVS'=>true, '_vti_cnf'=>true, 'simpletest'=>true, 'db'=>true, 'yui'=>true, 'tests'=>true, 'classes'=>true);
/** @var array list plugin types that support subplugins, do not add more here unless absolutely necessary */
protected static $supportsubplugins = array('mod', 'editor');
protected static $supportsubplugins = array('mod', 'editor', 'local');
/** @var null cache of plugin types */
protected static $plugintypes = null;
@@ -326,29 +326,69 @@ $cache = '.var_export($cache, true).';
}
foreach (self::$supportsubplugins as $type) {
$subpluginowners = self::fetch_plugins($type, $types[$type]);
foreach ($subpluginowners as $ownerdir) {
if (file_exists("$ownerdir/db/subplugins.php")) {
$subplugins = array();
include("$ownerdir/db/subplugins.php");
foreach ($subplugins as $subtype => $dir) {
if (!preg_match('/^[a-z][a-z0-9]*$/', $subtype)) {
error_log("Invalid subtype '$subtype'' detected in '$ownerdir', invalid characters present.");
continue;
}
if (isset(self::$subsystems[$subtype])) {
error_log("Invalid subtype '$subtype'' detected in '$ownerdir', duplicates core subsystem.");
continue;
}
$types[$subtype] = $CFG->dirroot.'/'.$dir;
}
if ($type === 'local') {
// Local subplugins must be after local plugins.
continue;
}
$subplugins = self::fetch_subplugins($type, $types[$type]);
foreach($subplugins as $subtype => $subplugin) {
if (isset($types[$subtype])) {
error_log("Invalid subtype '$subtype', duplicate detected.");
continue;
}
$types[$subtype] = $subplugin;
}
}
// Local is always last!
$types['local'] = $CFG->dirroot.'/local';
if (in_array('local', self::$supportsubplugins)) {
$subplugins = self::fetch_subplugins('local', $types['local']);
foreach($subplugins as $subtype => $subplugin) {
if (isset($types[$subtype])) {
error_log("Invalid subtype '$subtype', duplicate detected.");
continue;
}
$types[$subtype] = $subplugin;
}
}
return $types;
}
/**
* Returns list of subtypes defined in given plugin type.
* @param string $type
* @param string $fulldir
* @return array
*/
protected static function fetch_subplugins($type, $fulldir) {
global $CFG;
$types = array();
$subpluginowners = self::fetch_plugins($type, $fulldir);
foreach ($subpluginowners as $ownerdir) {
if (file_exists("$ownerdir/db/subplugins.php")) {
$subplugins = array();
include("$ownerdir/db/subplugins.php");
foreach ($subplugins as $subtype => $dir) {
if (!preg_match('/^[a-z][a-z0-9]*$/', $subtype)) {
error_log("Invalid subtype '$subtype'' detected in '$ownerdir', invalid characters present.");
continue;
}
if (isset(self::$subsystems[$subtype])) {
error_log("Invalid subtype '$subtype'' detected in '$ownerdir', duplicates core subsystem.");
continue;
}
if (!is_dir("$CFG->dirroot/$dir")) {
error_log("Invalid subtype directory '$dir' detected in '$ownerdir'.");
continue;
}
$types[$subtype] = "$CFG->dirroot/$dir";
}
}
}
return $types;
}
@@ -681,4 +721,18 @@ $cache = '.var_export($cache, true).';
return self::get_plugin_directory($type, $plugin);
}
/**
* Returns list of plugin types that allow subplugins.
* @return array as (string)plugintype => (string)fulldir
*/
public static function get_plugin_types_with_subplugins() {
self::init();
$return = array();
foreach (self::$supportsubplugins as $type) {
$return[$type] = self::$plugintypes[$type];
}
return $return;
}
}
+4 -7
View File
@@ -143,8 +143,8 @@ class plugin_manager {
// Hack: include mod and editor subplugin management classes first,
// the adminlib.php is supposed to contain extra admin settings too.
require_once($CFG->libdir.'/adminlib.php');
foreach(array('mod', 'editor') as $type) {
foreach (get_plugin_list($type) as $dir) {
foreach (core_component::get_plugin_types_with_subplugins() as $type => $ignored) {
foreach (core_component::get_plugin_list($type) as $dir) {
if (file_exists("$dir/adminlib.php")) {
include_once("$dir/adminlib.php");
}
@@ -221,8 +221,6 @@ class plugin_manager {
* Returns list of plugins that define their subplugins and the information
* about them from the db/subplugins.php file.
*
* At the moment, only activity modules and editors can define subplugins.
*
* @param bool $disablecache force reload, cache can be used otherwise
* @return array with keys like 'mod_quiz', and values the data from the
* corresponding db/subplugins.php file.
@@ -231,9 +229,8 @@ class plugin_manager {
if ($disablecache or is_null($this->subpluginsinfo)) {
$this->subpluginsinfo = array();
foreach (array('mod', 'editor') as $type) {
$owners = get_plugin_list($type);
foreach ($owners as $component => $ownerdir) {
foreach (core_component::get_plugin_types_with_subplugins() as $type => $ignored) {
foreach (core_component::get_plugin_list($type) as $component => $ownerdir) {
$componentsubplugins = array();
if (file_exists($ownerdir . '/db/subplugins.php')) {
$subplugins = array();
+15
View File
@@ -327,4 +327,19 @@ class core_component_testcase extends advanced_testcase {
$this->assertSame($fulldir, get_component_directory(('core_'.$subsystem)));
}
}
public function test_get_plugin_types_with_subplugins() {
global $CFG;
$types = core_component::get_plugin_types_with_subplugins();
// Hardcode it here to detect if anybody hacks the code to include more types.
$expected = array(
'mod' => "$CFG->dirroot/mod",
'editor' => "$CFG->dirroot/lib/editor",
'local' => "$CFG->dirroot/local",
);
$this->assertSame($expected, $types);
}
}