MDL-31989 component: Allow classes to be retrieved by namespace
authorDavid Monllao <davidm@moodle.com>
Wed, 17 Feb 2016 03:48:06 +0000 (11:48 +0800)
committerDan Poltawski <dan@moodle.com>
Tue, 23 Feb 2016 10:47:58 +0000 (10:47 +0000)
lib/classes/component.php
lib/tests/component_test.php

index bde0ae0..4fcad15 100644 (file)
@@ -397,7 +397,7 @@ $cache = '.var_export($cache, true).';
             'repository'  => $CFG->dirroot.'/repository',
             'rss'         => $CFG->dirroot.'/rss',
             'role'        => $CFG->dirroot.'/'.$CFG->admin.'/roles',
             'repository'  => $CFG->dirroot.'/repository',
             'rss'         => $CFG->dirroot.'/rss',
             'role'        => $CFG->dirroot.'/'.$CFG->admin.'/roles',
-            'search'      => null,
+            'search'      => $CFG->dirroot.'/search',
             'table'       => null,
             'tag'         => $CFG->dirroot.'/tag',
             'timezones'   => null,
             'table'       => null,
             'tag'         => $CFG->dirroot.'/tag',
             'timezones'   => null,
@@ -439,6 +439,7 @@ $cache = '.var_export($cache, true).';
             'webservice'    => $CFG->dirroot.'/webservice',
             'repository'    => $CFG->dirroot.'/repository',
             'portfolio'     => $CFG->dirroot.'/portfolio',
             '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',
             'qbehaviour'    => $CFG->dirroot.'/question/behaviour',
             'qformat'       => $CFG->dirroot.'/question/format',
             'plagiarism'    => $CFG->dirroot.'/plagiarism',
@@ -897,6 +898,39 @@ $cache = '.var_export($cache, true).';
         return $pluginfiles;
     }
 
         return $pluginfiles;
     }
 
+    /**
+     * Returns all classes in a component matching the provided namespace.
+     *
+     * It checks that the class exists.
+     *
+     * e.g. get_component_classes_in_namespace('mod_forum', 'event')
+     *
+     * @param string $component A valid moodle component (frankenstyle)
+     * @param string $namespace Namespace from the component name.
+     * @return array The full class name as key and the class path as value.
+     */
+    public static function get_component_classes_in_namespace($component, $namespace = '') {
+
+        // We will add them later.
+        $namespace = ltrim($namespace, '\\');
+
+        // We need add double backslashes as it is how classes are stored into self::$classmap.
+        $namespace = implode('\\\\', explode('\\', $namespace));
+
+        $regex = '/^' . $component . '\\\\' . $namespace . '/';
+        $it = new RegexIterator(new ArrayIterator(self::$classmap), $regex, RegexIterator::GET_MATCH, RegexIterator::USE_KEY);
+
+        // We want to be sure that they exist.
+        $classes = array();
+        foreach ($it as $classname => $classpath) {
+            if (class_exists($classname)) {
+                $classes[$classname] = $classpath;
+            }
+        }
+
+        return $classes;
+    }
+
     /**
      * Returns the exact absolute path to plugin directory.
      *
     /**
      * Returns the exact absolute path to plugin directory.
      *
index d5f0b55..f7b31c8 100644 (file)
@@ -451,4 +451,22 @@ class core_component_testcase extends advanced_testcase {
         $list = core_component::get_plugin_list_with_file('report', 'idontexist.php', true);
         $this->assertEquals(array(), array_keys($list));
     }
         $list = core_component::get_plugin_list_with_file('report', 'idontexist.php', true);
         $this->assertEquals(array(), array_keys($list));
     }
+
+    public function test_get_component_classes_int_namespace() {
+
+        // Unexisting.
+        $this->assertCount(0, core_component::get_component_classes_in_namespace('core_unexistingcomponent', 'something'));
+        $this->assertCount(0, core_component::get_component_classes_in_namespace('auth_cas', 'something'));
+
+        // Prefix with backslash if it doesn\'t come prefixed.
+        $this->assertCount(1, core_component::get_component_classes_in_namespace('auth_cas', 'task'));
+        $this->assertCount(1, core_component::get_component_classes_in_namespace('auth_cas', '\\task'));
+
+        // Core as a component works.
+        $this->assertCount(7, core_component::get_component_classes_in_namespace('core', 'update'));
+
+        // Multiple levels.
+        $this->assertCount(5, core_component::get_component_classes_in_namespace('core_user', '\\output\\myprofile\\'));
+        $this->assertCount(5, core_component::get_component_classes_in_namespace('core_user', '\\output\\myprofile'));
+    }
 }
 }