MDL-65646 core: Move component storage to json
authorAndrew Nicols <andrew@nicols.co.uk>
Tue, 12 Feb 2019 14:03:12 +0000 (22:03 +0800)
committerAndrew Nicols <andrew@nicols.co.uk>
Thu, 13 Jun 2019 04:26:00 +0000 (12:26 +0800)
31 files changed:
admin/tool/log/db/subplugins.json [new file with mode: 0644]
admin/tool/log/db/subplugins.php
backup/util/plan/backup_structure_step.class.php
backup/util/plan/restore_structure_step.class.php
backup/util/plan/tests/step_test.php
lib/accesslib.php
lib/adminlib.php
lib/classes/component.php
lib/classes/plugin_manager.php
lib/components.json [new file with mode: 0644]
lib/editor/atto/db/subplugins.json [new file with mode: 0644]
lib/editor/atto/db/subplugins.php
lib/editor/tinymce/db/subplugins.json [new file with mode: 0644]
lib/editor/tinymce/db/subplugins.php
lib/upgrade.txt
mod/assign/db/subplugins.json [new file with mode: 0644]
mod/assign/db/subplugins.php
mod/assignment/db/subplugins.json [new file with mode: 0644]
mod/assignment/db/subplugins.php
mod/book/db/subplugins.json [new file with mode: 0644]
mod/book/db/subplugins.php
mod/data/db/subplugins.json [new file with mode: 0644]
mod/data/db/subplugins.php
mod/lti/db/subplugins.json [new file with mode: 0644]
mod/lti/db/subplugins.php
mod/quiz/db/subplugins.json [new file with mode: 0644]
mod/quiz/db/subplugins.php
mod/scorm/db/subplugins.json [new file with mode: 0644]
mod/scorm/db/subplugins.php
mod/workshop/db/subplugins.json [new file with mode: 0644]
mod/workshop/db/subplugins.php

diff --git a/admin/tool/log/db/subplugins.json b/admin/tool/log/db/subplugins.json
new file mode 100644 (file)
index 0000000..3c8f43f
--- /dev/null
@@ -0,0 +1,5 @@
+{
+    "plugintypes": {
+        "logstore": "admin\/tool\/log\/store"
+    }
+}
index 9d1fe61..538c286 100644 (file)
@@ -22,4 +22,5 @@
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
-$subplugins = array('logstore' => 'admin/tool/log/store');
+debugging('Use of subplugins.php has been deprecated. Please provide a subplugins.json instead.', DEBUG_DEVELOPER);
+$subplugins = (array) json_decode(file_get_contents(__DIR__ . "/subplugins.json"))->plugintypes;
index e18ada4..e94cfe8 100644 (file)
@@ -173,7 +173,7 @@ abstract class backup_structure_step extends backup_step {
      * looking for /mod/modulenanme subplugins. This new method is a generalization of the
      * existing one for activities, supporting all subplugins injecting information everywhere.
      *
-     * @param string $subplugintype type of subplugin as defined in plugin's db/subplugins.php.
+     * @param string $subplugintype type of subplugin as defined in plugin's db/subplugins.json.
      * @param backup_nested_element $element element in the backup tree (anywhere) that
      *                                       we are going to add subplugin information to.
      * @param bool $multiple to define if multiple subplugins can produce information
@@ -206,11 +206,10 @@ abstract class backup_structure_step extends backup_step {
         }
 
         // Check the requested subplugintype is a valid one.
-        $subpluginsfile = core_component::get_component_directory($plugintype . '_' . $pluginname) . '/db/subplugins.php';
-        if (!file_exists($subpluginsfile)) {
-             throw new backup_step_exception('plugin_missing_subplugins_php_file', array($plugintype, $pluginname));
+        $subplugins = core_component::get_subplugins("{$plugintype}_{$pluginname}");
+        if (null === $subplugins) {
+            throw new backup_step_exception('plugin_missing_subplugins_configuration', [$plugintype, $pluginname]);
         }
-        include($subpluginsfile);
         if (!array_key_exists($subplugintype, $subplugins)) {
              throw new backup_step_exception('incorrect_subplugin_type', $subplugintype);
         }
index b59ac82..bffc7b7 100644 (file)
@@ -305,7 +305,7 @@ abstract class restore_structure_step extends restore_step {
      * looking for /mod/modulenanme subplugins. This new method is a generalization of the
      * existing one for activities, supporting all subplugins injecting information everywhere.
      *
-     * @param string $subplugintype type of subplugin as defined in plugin's db/subplugins.php.
+     * @param string $subplugintype type of subplugin as defined in plugin's db/subplugins.json.
      * @param restore_path_element $element element in the structure restore tree that
      *                              we are going to add subplugin information to.
      * @param string $plugintype type of the plugin.
@@ -336,11 +336,10 @@ abstract class restore_structure_step extends restore_step {
         }
 
         // Check the requested subplugintype is a valid one.
-        $subpluginsfile = core_component::get_component_directory($plugintype . '_' . $pluginname) . '/db/subplugins.php';
-        if (!file_exists($subpluginsfile)) {
-            throw new restore_step_exception('plugin_missing_subplugins_php_file', array($plugintype, $pluginname));
+        $subplugins = core_component::get_subplugins("{$plugintype}_{$pluginname}");
+        if (null === $subplugins) {
+            throw new restore_step_exception('plugin_missing_subplugins_configuration', array($plugintype, $pluginname));
         }
-        include($subpluginsfile);
         if (!array_key_exists($subplugintype, $subplugins)) {
              throw new restore_step_exception('incorrect_subplugin_type', $subplugintype);
         }
index 0cc854b..8b9f6e1 100644 (file)
@@ -241,7 +241,7 @@ class backup_step_testcase extends advanced_testcase {
             $this->assertTrue(false, 'base_step_exception expected');
         } catch (exception $e) {
             $this->assertTrue($e instanceof backup_step_exception);
-            $this->assertEquals('plugin_missing_subplugins_php_file', $e->errorcode);
+            $this->assertEquals('plugin_missing_subplugins_configuration', $e->errorcode);
         }
         // Wrong BC (defaulting to mod and modulename) use not having subplugins.
         try {
@@ -250,7 +250,7 @@ class backup_step_testcase extends advanced_testcase {
             $this->assertTrue(false, 'base_step_exception expected');
         } catch (exception $e) {
             $this->assertTrue($e instanceof backup_step_exception);
-            $this->assertEquals('plugin_missing_subplugins_php_file', $e->errorcode);
+            $this->assertEquals('plugin_missing_subplugins_configuration', $e->errorcode);
         }
         // Wrong subplugin type.
         try {
@@ -362,7 +362,7 @@ class backup_step_testcase extends advanced_testcase {
             $this->assertTrue(false, 'base_step_exception expected');
         } catch (exception $e) {
             $this->assertTrue($e instanceof restore_step_exception);
-            $this->assertEquals('plugin_missing_subplugins_php_file', $e->errorcode);
+            $this->assertEquals('plugin_missing_subplugins_configuration', $e->errorcode);
         }
         // Wrong BC (defaulting to mod and modulename) use not having subplugins.
         try {
@@ -371,7 +371,7 @@ class backup_step_testcase extends advanced_testcase {
             $this->assertTrue(false, 'base_step_exception expected');
         } catch (exception $e) {
             $this->assertTrue($e instanceof restore_step_exception);
-            $this->assertEquals('plugin_missing_subplugins_php_file', $e->errorcode);
+            $this->assertEquals('plugin_missing_subplugins_configuration', $e->errorcode);
         }
         // Wrong subplugin type.
         try {
index e80ba19..856c556 100644 (file)
@@ -7010,20 +7010,27 @@ class context_module extends context {
         $module = $DB->get_record('modules', array('id'=>$cm->module));
 
         $subcaps = array();
-        $subpluginsfile = "$CFG->dirroot/mod/$module->name/db/subplugins.php";
-        if (file_exists($subpluginsfile)) {
+
+        $modulepath = "{$CFG->dirroot}/mod/{$module->name}";
+        if (file_exists("{$modulepath}/db/subplugins.json")) {
+            $subplugins = (array) json_decode(file_get_contents("{$modulepath}/db/subplugins.json"))->plugintypes;
+        } else if (file_exists("{$modulepath}/db/subplugins.php")) {
+            debugging('Use of subplugins.php has been deprecated. ' .
+                    'Please update your plugin to provide a subplugins.json file instead.',
+                    DEBUG_DEVELOPER);
             $subplugins = array();  // should be redefined in the file
-            include($subpluginsfile);
-            if (!empty($subplugins)) {
-                foreach (array_keys($subplugins) as $subplugintype) {
-                    foreach (array_keys(core_component::get_plugin_list($subplugintype)) as $subpluginname) {
-                        $subcaps = array_merge($subcaps, array_keys(load_capability_def($subplugintype.'_'.$subpluginname)));
-                    }
+            include("{$modulepath}/db/subplugins.php");
+        }
+
+        if (!empty($subplugins)) {
+            foreach (array_keys($subplugins) as $subplugintype) {
+                foreach (array_keys(core_component::get_plugin_list($subplugintype)) as $subpluginname) {
+                    $subcaps = array_merge($subcaps, array_keys(load_capability_def($subplugintype.'_'.$subpluginname)));
                 }
             }
         }
 
-        $modfile = "$CFG->dirroot/mod/$module->name/lib.php";
+        $modfile = "{$modulepath}/lib.php";
         $extracaps = array();
         if (file_exists($modfile)) {
             include_once($modfile);
index 07f66e4..8e48444 100644 (file)
@@ -132,17 +132,26 @@ function uninstall_plugin($type, $name) {
     $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) {
+
+        $subpluginsfile = "{$base}/db/subplugins.json";
+        if (file_exists($subpluginsfile)) {
+            $subplugins = (array) json_decode(file_get_contents($subpluginsfile))->plugintypes;
+        } else if (file_exists("{$base}/db/subplugins.php")) {
+            debugging('Use of subplugins.php has been deprecated. ' .
+                    'Please update your plugin to provide a subplugins.json file instead.',
+                    DEBUG_DEVELOPER);
+            $subplugins = [];
+            include("{$base}/db/subplugins.php");
+        }
+
+        if (!empty($subplugins)) {
+            foreach (array_keys($subplugins) as $subplugintype) {
                 $instances = core_component::get_plugin_list($subplugintype);
                 foreach ($instances as $subpluginname => $notusedpluginpath) {
                     uninstall_plugin($subplugintype, $subpluginname);
                 }
             }
         }
-
     }
 
     $component = $type . '_' . $name;  // eg. 'qtype_multichoice' or 'workshopgrading_accumulative' or 'mod_forum'
index 6c5d842..2f1d336 100644 (file)
@@ -47,6 +47,8 @@ class core_component {
     /** @var array list plugin types that support subplugins, do not add more here unless absolutely necessary */
     protected static $supportsubplugins = array('mod', 'editor', 'tool', 'local');
 
+    /** @var object JSON source of the component data */
+    protected static $componentsource = null;
     /** @var array cache of plugin types */
     protected static $plugintypes = null;
     /** @var array cache of plugin locations */
@@ -416,79 +418,20 @@ $cache = '.var_export($cache, true).';
         global $CFG;
 
         // NOTE: Any additions here must be verified to not collide with existing add-on modules and subplugins!!!
+        $info = [];
+        foreach (self::fetch_component_source('subsystems') as $subsystem => $path) {
+            // Replace admin/ directory with the config setting.
+            if ($CFG->admin !== 'admin') {
+                if ($path === 'admin') {
+                    $path = $CFG->admin;
+                }
+                if (strpos($path, 'admin/') === 0) {
+                    $path = $CFG->admin . substr($path, 0, 5);
+                }
+            }
 
-        $info = array(
-            'access'      => null,
-            'admin'       => $CFG->dirroot.'/'.$CFG->admin,
-            'analytics'   => $CFG->dirroot . '/analytics',
-            'antivirus'   => $CFG->dirroot . '/lib/antivirus',
-            'auth'        => $CFG->dirroot.'/auth',
-            'availability' => $CFG->dirroot . '/availability',
-            'backup'      => $CFG->dirroot.'/backup/util/ui',
-            'badges'      => $CFG->dirroot.'/badges',
-            'block'       => $CFG->dirroot.'/blocks',
-            'blog'        => $CFG->dirroot.'/blog',
-            'bulkusers'   => null,
-            'cache'       => $CFG->dirroot.'/cache',
-            'calendar'    => $CFG->dirroot.'/calendar',
-            'cohort'      => $CFG->dirroot.'/cohort',
-            'comment'     => $CFG->dirroot.'/comment',
-            'competency'  => $CFG->dirroot.'/competency',
-            'completion'  => $CFG->dirroot.'/completion',
-            'countries'   => null,
-            'course'      => $CFG->dirroot.'/course',
-            'currencies'  => null,
-            'customfield' => $CFG->dirroot.'/customfield',
-            'dbtransfer'  => null,
-            'debug'       => null,
-            'editor'      => $CFG->dirroot.'/lib/editor',
-            'edufields'   => null,
-            'enrol'       => $CFG->dirroot.'/enrol',
-            'error'       => null,
-            'favourites'  => $CFG->dirroot . '/favourites',
-            'filepicker'  => null,
-            'fileconverter' => $CFG->dirroot.'/files/converter',
-            'files'       => $CFG->dirroot.'/files',
-            'filters'     => $CFG->dirroot.'/filter',
-            //'fonts'       => null, // Bogus.
-            'form'        => $CFG->dirroot.'/lib/form',
-            'grades'      => $CFG->dirroot.'/grade',
-            'grading'     => $CFG->dirroot.'/grade/grading',
-            'group'       => $CFG->dirroot.'/group',
-            'help'        => null,
-            'hub'         => null,
-            'imscc'       => null,
-            'install'     => null,
-            'iso6392'     => null,
-            'langconfig'  => null,
-            'license'     => null,
-            'mathslib'    => null,
-            'media'       => $CFG->dirroot.'/media',
-            'message'     => $CFG->dirroot.'/message',
-            'mimetypes'   => null,
-            'mnet'        => $CFG->dirroot.'/mnet',
-            //'moodle.org'  => null, // Not used any more.
-            'my'          => $CFG->dirroot.'/my',
-            'notes'       => $CFG->dirroot.'/notes',
-            'pagetype'    => null,
-            'pix'         => null,
-            'plagiarism'  => $CFG->dirroot.'/plagiarism',
-            'plugin'      => null,
-            'portfolio'   => $CFG->dirroot.'/portfolio',
-            'privacy'     => $CFG->dirroot . '/privacy',
-            'question'    => $CFG->dirroot.'/question',
-            'rating'      => $CFG->dirroot.'/rating',
-            'repository'  => $CFG->dirroot.'/repository',
-            'rss'         => $CFG->dirroot.'/rss',
-            'role'        => $CFG->dirroot.'/'.$CFG->admin.'/roles',
-            'search'      => $CFG->dirroot.'/search',
-            'table'       => null,
-            'tag'         => $CFG->dirroot.'/tag',
-            'timezones'   => null,
-            'user'        => $CFG->dirroot.'/user',
-            'userkey'     => $CFG->dirroot.'/lib/userkey',
-            'webservice'  => $CFG->dirroot.'/webservice',
-        );
+            $info[$subsystem] = empty($path) ? null : "{$CFG->dirroot}/{$path}";
+        }
 
         return $info;
     }
@@ -500,43 +443,15 @@ $cache = '.var_export($cache, true).';
     protected static function fetch_plugintypes() {
         global $CFG;
 
-        $types = array(
-            'antivirus'     => $CFG->dirroot . '/lib/antivirus',
-            'availability'  => $CFG->dirroot . '/availability/condition',
-            'qtype'         => $CFG->dirroot.'/question/type',
-            'mod'           => $CFG->dirroot.'/mod',
-            'auth'          => $CFG->dirroot.'/auth',
-            'calendartype'  => $CFG->dirroot.'/calendar/type',
-            'customfield'   => $CFG->dirroot.'/customfield/field',
-            'enrol'         => $CFG->dirroot.'/enrol',
-            'message'       => $CFG->dirroot.'/message/output',
-            'block'         => $CFG->dirroot.'/blocks',
-            'media'         => $CFG->dirroot.'/media/player',
-            'filter'        => $CFG->dirroot.'/filter',
-            'editor'        => $CFG->dirroot.'/lib/editor',
-            'format'        => $CFG->dirroot.'/course/format',
-            'dataformat'    => $CFG->dirroot.'/dataformat',
-            'profilefield'  => $CFG->dirroot.'/user/profile/field',
-            'report'        => $CFG->dirroot.'/report',
-            'coursereport'  => $CFG->dirroot.'/course/report', // Must be after system reports.
-            'gradeexport'   => $CFG->dirroot.'/grade/export',
-            'gradeimport'   => $CFG->dirroot.'/grade/import',
-            'gradereport'   => $CFG->dirroot.'/grade/report',
-            'gradingform'   => $CFG->dirroot.'/grade/grading/form',
-            'mlbackend'     => $CFG->dirroot.'/lib/mlbackend',
-            'mnetservice'   => $CFG->dirroot.'/mnet/service',
-            'webservice'    => $CFG->dirroot.'/webservice',
-            'repository'    => $CFG->dirroot.'/repository',
-            'portfolio'     => $CFG->dirroot.'/portfolio',
-            'search'        => $CFG->dirroot.'/search/engine',
-            'qbehaviour'    => $CFG->dirroot.'/question/behaviour',
-            'qformat'       => $CFG->dirroot.'/question/format',
-            'plagiarism'    => $CFG->dirroot.'/plagiarism',
-            'tool'          => $CFG->dirroot.'/'.$CFG->admin.'/tool',
-            'cachestore'    => $CFG->dirroot.'/cache/stores',
-            'cachelock'     => $CFG->dirroot.'/cache/locks',
-            'fileconverter' => $CFG->dirroot.'/files/converter',
-        );
+        $types = [];
+        foreach (self::fetch_component_source('plugintypes') as $plugintype => $path) {
+            // Replace admin/ with the config setting.
+            if ($CFG->admin !== 'admin' && strpos($path, 'admin/') === 0) {
+                $path = $CFG->admin . substr($path, 0, 5);
+            }
+            $types[$plugintype] = "{$CFG->dirroot}/{$path}";
+        }
+
         $parents = array();
         $subplugins = array();
 
@@ -596,6 +511,19 @@ $cache = '.var_export($cache, true).';
         return array($types, $parents, $subplugins);
     }
 
+    /**
+     * Returns the component source content as loaded from /lib/components.json.
+     *
+     * @return array
+     */
+    protected static function fetch_component_source(string $key) {
+        if (null === self::$componentsource) {
+            self::$componentsource = (array) json_decode(file_get_contents(__DIR__ . '/../components.json'));
+        }
+
+        return (array) self::$componentsource[$key];
+    }
+
     /**
      * Returns list of subtypes.
      * @param string $ownerdir
@@ -605,28 +533,35 @@ $cache = '.var_export($cache, true).';
         global $CFG;
 
         $types = array();
-        if (file_exists("$ownerdir/db/subplugins.php")) {
-            $subplugins = array();
+        $subplugins = array();
+        if (file_exists("$ownerdir/db/subplugins.json")) {
+            $subplugins = (array) json_decode(file_get_contents("$ownerdir/db/subplugins.json"))->plugintypes;
+        } else if (file_exists("$ownerdir/db/subplugins.php")) {
+            debugging('Use of subplugins.php has been deprecated. ' .
+                    'Please update your plugin to provide a subplugins.json file instead.',
+                    DEBUG_DEVELOPER);
             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 ($CFG->admin !== 'admin' and strpos($dir, 'admin/') === 0) {
-                    $dir = preg_replace('|^admin/|', "$CFG->admin/", $dir);
-                }
-                if (!is_dir("$CFG->dirroot/$dir")) {
-                    error_log("Invalid subtype directory '$dir' detected in '$ownerdir'.");
-                    continue;
-                }
-                $types[$subtype] = "$CFG->dirroot/$dir";
+        }
+
+        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 ($CFG->admin !== 'admin' and strpos($dir, 'admin/') === 0) {
+                $dir = preg_replace('|^admin/|', "$CFG->admin/", $dir);
+            }
+            if (!is_dir("$CFG->dirroot/$dir")) {
+                error_log("Invalid subtype directory '$dir' detected in '$ownerdir'.");
+                continue;
+            }
+            $types[$subtype] = "$CFG->dirroot/$dir";
         }
+
         return $types;
     }
 
index 4eaa742..ce5442f 100644 (file)
@@ -511,10 +511,10 @@ class core_plugin_manager {
 
     /**
      * Returns list of plugins that define their subplugins and the information
-     * about them from the db/subplugins.php file.
+     * about them from the db/subplugins.json file.
      *
      * @return array with keys like 'mod_quiz', and values the data from the
-     *      corresponding db/subplugins.php file.
+     *      corresponding db/subplugins.json file.
      */
     public function get_subplugins() {
 
diff --git a/lib/components.json b/lib/components.json
new file mode 100644 (file)
index 0000000..8ca41cf
--- /dev/null
@@ -0,0 +1,111 @@
+{
+    "plugintypes": {
+        "antivirus": "lib\/antivirus",
+        "availability": "availability\/condition",
+        "qtype": "question\/type",
+        "mod": "mod",
+        "auth": "auth",
+        "calendartype": "calendar\/type",
+        "customfield": "customfield\/field",
+        "enrol": "enrol",
+        "message": "message\/output",
+        "block": "blocks",
+        "media": "media\/player",
+        "filter": "filter",
+        "editor": "lib\/editor",
+        "format": "course\/format",
+        "dataformat": "dataformat",
+        "profilefield": "user\/profile\/field",
+        "report": "report",
+        "coursereport": "course\/report",
+        "gradeexport": "grade\/export",
+        "gradeimport": "grade\/import",
+        "gradereport": "grade\/report",
+        "gradingform": "grade\/grading\/form",
+        "mlbackend": "lib\/mlbackend",
+        "mnetservice": "mnet\/service",
+        "webservice": "webservice",
+        "repository": "repository",
+        "portfolio": "portfolio",
+        "search": "search\/engine",
+        "qbehaviour": "question\/behaviour",
+        "qformat": "question\/format",
+        "plagiarism": "plagiarism",
+        "tool": "admin\/tool",
+        "cachestore": "cache\/stores",
+        "cachelock": "cache\/locks",
+        "fileconverter": "files\/converter",
+        "theme": "theme",
+        "local": "local"
+    },
+    "subsystems": {
+        "access": null,
+        "admin": "admin",
+        "analytics": "analytics",
+        "antivirus": "lib\/antivirus",
+        "auth": "auth",
+        "availability": "availability",
+        "backup": "backup\/util\/ui",
+        "badges": "badges",
+        "block": "blocks",
+        "blog": "blog",
+        "bulkusers": null,
+        "cache": "cache",
+        "calendar": "calendar",
+        "cohort": "cohort",
+        "comment": "comment",
+        "competency": "competency",
+        "completion": "completion",
+        "countries": null,
+        "course": "course",
+        "currencies": null,
+        "customfield": "customfield",
+        "dbtransfer": null,
+        "debug": null,
+        "editor": "lib\/editor",
+        "edufields": null,
+        "enrol": "enrol",
+        "error": null,
+        "favourites": "favourites",
+        "filepicker": null,
+        "fileconverter": "files\/converter",
+        "files": "files",
+        "filters": "filter",
+        "form": "lib\/form",
+        "grades": "grade",
+        "grading": "grade\/grading",
+        "group": "group",
+        "help": null,
+        "hub": null,
+        "imscc": null,
+        "install": null,
+        "iso6392": null,
+        "langconfig": null,
+        "license": null,
+        "mathslib": null,
+        "media": "media",
+        "message": "message",
+        "mimetypes": null,
+        "mnet": "mnet",
+        "my": "my",
+        "notes": "notes",
+        "pagetype": null,
+        "pix": null,
+        "plagiarism": "plagiarism",
+        "plugin": null,
+        "portfolio": "portfolio",
+        "privacy": "privacy",
+        "question": "question",
+        "rating": "rating",
+        "repository": "repository",
+        "rss": "rss",
+        "role": "admin\/roles",
+        "search": "search",
+        "table": null,
+        "tag": "tag",
+        "timezones": null,
+        "user": "user",
+        "userkey": "lib\/userkey",
+        "webservice": "webservice"
+    }
+}
diff --git a/lib/editor/atto/db/subplugins.json b/lib/editor/atto/db/subplugins.json
new file mode 100644 (file)
index 0000000..d9b9d8c
--- /dev/null
@@ -0,0 +1,5 @@
+{
+    "plugintypes": {
+        "atto": "lib\/editor\/atto\/plugins"
+    }
+}
index de0b440..7500a5f 100644 (file)
@@ -24,4 +24,5 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$subplugins = array('atto' => 'lib/editor/atto/plugins');
+debugging('Use of subplugins.php has been deprecated. Please provide a subplugins.json instead.', DEBUG_DEVELOPER);
+$subplugins = (array) json_decode(file_get_contents(__DIR__ . "/subplugins.json"))->plugintypes;
diff --git a/lib/editor/tinymce/db/subplugins.json b/lib/editor/tinymce/db/subplugins.json
new file mode 100644 (file)
index 0000000..f6c8601
--- /dev/null
@@ -0,0 +1,5 @@
+{
+    "plugintypes": {
+        "tinymce": "lib\/editor\/tinymce\/plugins"
+    }
+}
index 68ef191..a5baea9 100644 (file)
@@ -24,4 +24,5 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$subplugins = array('tinymce' => 'lib/editor/tinymce/plugins');
+debugging('Use of subplugins.php has been deprecated. Please provide a subplugins.json instead.', DEBUG_DEVELOPER);
+$subplugins = (array) json_decode(file_get_contents(__DIR__ . "/subplugins.json"))->plugintypes;
index 631f3e6..4c8b4c3 100644 (file)
@@ -3,6 +3,8 @@ information provided here is intended especially for developers.
 
 === 3.8 ===
 * The yui checknet module is removed. Call \core\session\manager::keepalive instead.
+* Core components are now defined in /lib/components.json instead of coded into /lib/classes/component.php
+* Subplugins should now be defined using /db/subplugins.json instead of /db/subplugins.php (which will still work in order to maintain backwards compantibility).
 
 === 3.7 ===
 * Nodes in the navigation api can have labels for each group. See set/get_collectionlabel().
diff --git a/mod/assign/db/subplugins.json b/mod/assign/db/subplugins.json
new file mode 100644 (file)
index 0000000..202a240
--- /dev/null
@@ -0,0 +1,6 @@
+{
+    "plugintypes": {
+        "assignsubmission": "mod\/assign\/submission",
+        "assignfeedback": "mod\/assign\/feedback"
+    }
+}
index be0d707..ce8b075 100644 (file)
@@ -22,4 +22,5 @@
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
-$subplugins = array('assignsubmission'=>'mod/assign/submission', 'assignfeedback'=>'mod/assign/feedback');
+debugging('Use of subplugins.php has been deprecated. Please provide a subplugins.json instead.', DEBUG_DEVELOPER);
+$subplugins = (array) json_decode(file_get_contents(__DIR__ . "/subplugins.json"))->plugintypes;
diff --git a/mod/assignment/db/subplugins.json b/mod/assignment/db/subplugins.json
new file mode 100644 (file)
index 0000000..7c6b9c0
--- /dev/null
@@ -0,0 +1,5 @@
+{
+    "plugintypes": {
+        "assignment": "mod\/assignment\/type"
+    }
+}
index 52e3b41..5ea3af4 100644 (file)
@@ -1,3 +1,26 @@
 <?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 
-$subplugins = array('assignment'=>'mod/assignment/type');
+/**
+ * Definition of sub-plugins
+ *
+ * @package     mod_assignment
+ * @copyright   1999 onwards Martin Dougiamas  {@link http://moodle.com}
+ * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+debugging('Use of subplugins.php has been deprecated. Please provide a subplugins.json instead.', DEBUG_DEVELOPER);
+$subplugins = (array) json_decode(file_get_contents(__DIR__ . "/subplugins.json"))->plugintypes;
diff --git a/mod/book/db/subplugins.json b/mod/book/db/subplugins.json
new file mode 100644 (file)
index 0000000..97e2827
--- /dev/null
@@ -0,0 +1,5 @@
+{
+    "plugintypes": {
+        "booktool": "mod\/book\/tool"
+    }
+}
index e3e2e90..5348581 100644 (file)
@@ -24,6 +24,5 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$subplugins = array(
-    'booktool'       => 'mod/book/tool',
-);
+debugging('Use of subplugins.php has been deprecated. Please provide a subplugins.json instead.', DEBUG_DEVELOPER);
+$subplugins = (array) json_decode(file_get_contents(__DIR__ . "/subplugins.json"))->plugintypes;
diff --git a/mod/data/db/subplugins.json b/mod/data/db/subplugins.json
new file mode 100644 (file)
index 0000000..67639a6
--- /dev/null
@@ -0,0 +1,6 @@
+{
+    "plugintypes": {
+        "datafield": "mod\/data\/field",
+        "datapreset": "mod\/data\/preset"
+    }
+}
index 2c1a7e9..d0dd67e 100644 (file)
@@ -1,4 +1,26 @@
 <?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 
-$subplugins = array('datafield'  => 'mod/data/field',
-                    'datapreset' => 'mod/data/preset');
+/**
+ * Definition of sub-plugins
+ *
+ * @package   mod_data
+ * @copyright 1999 onwards Martin Dougiamas  {@link http://moodle.com}
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+debugging('Use of subplugins.php has been deprecated. Please provide a subplugins.json instead.', DEBUG_DEVELOPER);
+$subplugins = (array) json_decode(file_get_contents(__DIR__ . "/subplugins.json"))->plugintypes;
diff --git a/mod/lti/db/subplugins.json b/mod/lti/db/subplugins.json
new file mode 100644 (file)
index 0000000..35f0d16
--- /dev/null
@@ -0,0 +1,6 @@
+{
+    "plugintypes": {
+        "ltisource": "mod\/lti\/source",
+        "ltiservice": "mod\/lti\/service"
+    }
+}
index d5244d2..13967c3 100644 (file)
@@ -24,7 +24,5 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$subplugins = array(
-    'ltisource' => 'mod/lti/source',
-    'ltiservice' => 'mod/lti/service'
-);
+debugging('Use of subplugins.php has been deprecated. Please provide a subplugins.json instead.', DEBUG_DEVELOPER);
+$subplugins = (array) json_decode(file_get_contents(__DIR__ . "/subplugins.json"))->plugintypes;
diff --git a/mod/quiz/db/subplugins.json b/mod/quiz/db/subplugins.json
new file mode 100644 (file)
index 0000000..d0d0c2c
--- /dev/null
@@ -0,0 +1,6 @@
+{
+    "plugintypes": {
+        "quiz": "mod\/quiz\/report",
+        "quizaccess": "mod\/quiz\/accessrule"
+    }
+}
index efcc67d..951d92d 100644 (file)
@@ -24,7 +24,5 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$subplugins = array(
-    'quiz' => 'mod/quiz/report',
-    'quizaccess' => 'mod/quiz/accessrule',
-);
+debugging('Use of subplugins.php has been deprecated. Please provide a subplugins.json instead.', DEBUG_DEVELOPER);
+$subplugins = (array) json_decode(file_get_contents(__DIR__ . "/subplugins.json"))->plugintypes;
diff --git a/mod/scorm/db/subplugins.json b/mod/scorm/db/subplugins.json
new file mode 100644 (file)
index 0000000..dd48250
--- /dev/null
@@ -0,0 +1,5 @@
+{
+    "plugintypes": {
+        "scormreport": "mod\/scorm\/report"
+    }
+}
index ac3aa87..f39017f 100644 (file)
@@ -14,4 +14,5 @@
 // You should have received a copy of the GNU General Public License
 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 
-$subplugins = array('scormreport' => 'mod/scorm/report');
+debugging('Use of subplugins.php has been deprecated. Please provide a subplugins.json instead.', DEBUG_DEVELOPER);
+$subplugins = (array) json_decode(file_get_contents(__DIR__ . "/subplugins.json"))->plugintypes;
diff --git a/mod/workshop/db/subplugins.json b/mod/workshop/db/subplugins.json
new file mode 100644 (file)
index 0000000..a6807bf
--- /dev/null
@@ -0,0 +1,7 @@
+{
+    "plugintypes": {
+        "workshopform": "mod\/workshop\/form",
+        "workshopallocation": "mod\/workshop\/allocation",
+        "workshopeval": "mod\/workshop\/eval"
+    }
+}
index 66260e8..1c0fd19 100644 (file)
@@ -1,5 +1,4 @@
 <?php
-
 // This file is part of Moodle - http://moodle.org/
 //
 // Moodle is free software: you can redistribute it and/or modify
@@ -25,8 +24,5 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-$subplugins = array(
-                    'workshopform'       => 'mod/workshop/form',
-                    'workshopallocation' => 'mod/workshop/allocation',
-                    'workshopeval'       => 'mod/workshop/eval',
-                    );
+debugging('Use of subplugins.php has been deprecated. Please provide a subplugins.json instead.', DEBUG_DEVELOPER);
+$subplugins = (array) json_decode(file_get_contents(__DIR__ . "/subplugins.json"))->plugintypes;