MDL-66903 core: Move core_component to \core\component

This commit is contained in:
Andrew Nicols 2024-07-05 09:39:17 +08:00
parent 406dcd2566
commit 25df1ed645
No known key found for this signature in database
GPG key ID: 6D1E3157C8CFBF14
4 changed files with 179 additions and 147 deletions

View file

@ -0,0 +1,11 @@
issueNumber: MDL-66903
notes:
core:
- message: |
The following classes have been renamed and now support autoloading.
Existing classes are currently unaffected.
| Old class name | New class name |
| --- | --- |
| `\core_component` | `\core\component` |
type: improved

View file

@ -22,6 +22,15 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/ */
namespace core;
use core\exception\coding_exception;
use stdClass;
use ArrayIterator;
use DirectoryIterator;
use Exception;
use RegexIterator;
// Constants used in version.php files, these must exist when core_component executes. // Constants used in version.php files, these must exist when core_component executes.
// We make use of error_log as debugging is not always available. // We make use of error_log as debugging is not always available.
@ -43,7 +52,7 @@ define('ANY_VERSION', 'any');
/** /**
* Collection of components related methods. * Collection of components related methods.
*/ */
class core_component { class component {
/** @var array list of ignored directories in plugin type roots - watch out for auth/db exception */ /** @var array list of ignored directories in plugin type roots - watch out for auth/db exception */
protected static $ignoreddirs = [ protected static $ignoreddirs = [
'CVS' => true, 'CVS' => true,
@ -160,7 +169,7 @@ class core_component {
$debugging = "Class '%s' has been renamed for the autoloader and is now deprecated. Please use '%s' instead."; $debugging = "Class '%s' has been renamed for the autoloader and is now deprecated. Please use '%s' instead.";
debugging(sprintf($debugging, $classname, $newclassname), DEBUG_DEVELOPER); debugging(sprintf($debugging, $classname, $newclassname), DEBUG_DEVELOPER);
if (PHP_VERSION_ID >= 70000 && preg_match('#\\\null(\\\|$)#', $classname)) { if (PHP_VERSION_ID >= 70000 && preg_match('#\\\null(\\\|$)#', $classname)) {
throw new \coding_exception("Cannot alias $classname to $newclassname"); throw new coding_exception("Cannot alias $classname to $newclassname");
} }
class_alias($newclassname, $classname); class_alias($newclassname, $classname);
return; return;
@ -728,7 +737,7 @@ $cache = ' . var_export($cache, true) . ';
if (!is_dir($fulldir)) { if (!is_dir($fulldir)) {
continue; continue;
} }
$items = new \DirectoryIterator($fulldir); $items = new DirectoryIterator($fulldir);
foreach ($items as $item) { foreach ($items as $item) {
if ($item->isDot() || !$item->isDir()) { if ($item->isDot() || !$item->isDir()) {
continue; continue;
@ -826,7 +835,7 @@ $cache = ' . var_export($cache, true) . ';
return; return;
} }
$items = new \DirectoryIterator($fulldir); $items = new DirectoryIterator($fulldir);
foreach ($items as $item) { foreach ($items as $item) {
if ($item->isDot()) { if ($item->isDot()) {
continue; continue;
@ -1500,13 +1509,13 @@ $cache = ' . var_export($cache, true) . ';
foreach ($legacyclasses as $classname => $path) { foreach ($legacyclasses as $classname => $path) {
if (is_array($path)) { if (is_array($path)) {
if (!$allowsubsystems) { if (!$allowsubsystems) {
throw new \Exception( throw new Exception(
"Invalid legacy classes path entry for {$classname}. " . "Invalid legacy classes path entry for {$classname}. " .
"Only files within the component can be specified.", "Only files within the component can be specified.",
); );
} }
if (count($path) !== 2) { if (count($path) !== 2) {
throw new \Exception( throw new Exception(
"Invalid legacy classes path entry for {$classname}. " . "Invalid legacy classes path entry for {$classname}. " .
"Entries must be in the format [subsystem, path].", "Entries must be in the format [subsystem, path].",
); );
@ -1514,7 +1523,7 @@ $cache = ' . var_export($cache, true) . ';
[$subsystem, $path] = $path; [$subsystem, $path] = $path;
$subsystem = substr($subsystem, 5); $subsystem = substr($subsystem, 5);
if (!array_key_exists($subsystem, self::$subsystems)) { if (!array_key_exists($subsystem, self::$subsystems)) {
throw new \Exception( throw new Exception(
"Unknown subsystem '{$subsystem}' for legacy classes entry of '{$classname}'", "Unknown subsystem '{$subsystem}' for legacy classes entry of '{$classname}'",
); );
} }
@ -1620,3 +1629,7 @@ $cache = ' . var_export($cache, true) . ';
return file_exists("$plugindir/pix/monologo.svg") || file_exists("$plugindir/pix/monologo.png"); return file_exists("$plugindir/pix/monologo.svg") || file_exists("$plugindir/pix/monologo.png");
} }
} }
// Alias this class to the old name.
// This should be kept here because we use this class in external tooling.
class_alias(component::class, \core_component::class);

View file

@ -80,7 +80,7 @@ abstract class advanced_testcase extends base_testcase {
$CFG = phpunit_util::get_global_backup('CFG'); $CFG = phpunit_util::get_global_backup('CFG');
$DB = phpunit_util::get_global_backup('DB'); $DB = phpunit_util::get_global_backup('DB');
// This is _hacky_. We need to reset the autoloader, and this is the only way to do so right now. // This is _hacky_. We need to reset the autoloader, and this is the only way to do so right now.
(new ReflectionProperty(\core_component::class, 'plugintypes'))->setValue(null, null); (new ReflectionProperty(\core\component::class, 'plugintypes'))->setValue(null, null);
} }
if (isset($e)) { if (isset($e)) {

View file

@ -14,19 +14,31 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
// phpcs:disable moodle.PHPUnit.TestCaseNames.MissingNS namespace core;
use DirectoryIterator;
use ReflectionClass;
use ReflectionProperty;
/** /**
* core_component related tests. * component related tests.
* *
* @package core * @package core
* @category test * @category test
* @copyright 2013 Petr Skoda {@link http://skodak.org} * @copyright 2013 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* *
* @covers \core_component * @covers \core\component
*/ */
final class component_test extends advanced_testcase { final class component_test extends \advanced_testcase {
#[\Override]
public function tearDown(): void {
$plugintypes = new ReflectionProperty(component::class, 'plugintypes');
$plugintypes->setValue(null, null);
parent::tearDown();
}
/** /**
* To be changed if number of subsystems increases/decreases, * To be changed if number of subsystems increases/decreases,
* this is defined here to annoy devs that try to add more without any thinking, * this is defined here to annoy devs that try to add more without any thinking,
@ -37,7 +49,7 @@ final class component_test extends advanced_testcase {
public function test_get_core_subsystems(): void { public function test_get_core_subsystems(): void {
global $CFG; global $CFG;
$subsystems = core_component::get_core_subsystems(); $subsystems = component::get_core_subsystems();
$this->assertCount( $this->assertCount(
self::SUBSYSTEMCOUNT, self::SUBSYSTEMCOUNT,
@ -96,7 +108,7 @@ final class component_test extends advanced_testcase {
public function test_deprecated_get_core_subsystems(): void { public function test_deprecated_get_core_subsystems(): void {
global $CFG; global $CFG;
$subsystems = core_component::get_core_subsystems(); $subsystems = component::get_core_subsystems();
$this->assertSame($subsystems, get_core_subsystems(true)); $this->assertSame($subsystems, get_core_subsystems(true));
@ -125,7 +137,7 @@ final class component_test extends advanced_testcase {
'Non-empty $CFG->themedir is not covered by any tests yet, you need to disable it.', 'Non-empty $CFG->themedir is not covered by any tests yet, you need to disable it.',
); );
$plugintypes = core_component::get_plugin_types(); $plugintypes = component::get_plugin_types();
foreach ($plugintypes as $plugintype => $fulldir) { foreach ($plugintypes as $plugintype => $fulldir) {
$this->assertStringStartsWith("$CFG->dirroot/", $fulldir); $this->assertStringStartsWith("$CFG->dirroot/", $fulldir);
@ -135,7 +147,7 @@ final class component_test extends advanced_testcase {
public function test_deprecated_get_plugin_types(): void { public function test_deprecated_get_plugin_types(): void {
global $CFG; global $CFG;
$plugintypes = core_component::get_plugin_types(); $plugintypes = component::get_plugin_types();
$this->assertSame($plugintypes, get_plugin_types()); $this->assertSame($plugintypes, get_plugin_types());
$this->assertSame($plugintypes, get_plugin_types(true)); $this->assertSame($plugintypes, get_plugin_types(true));
@ -151,10 +163,10 @@ final class component_test extends advanced_testcase {
public function test_get_plugin_list(): void { public function test_get_plugin_list(): void {
global $CFG; global $CFG;
$plugintypes = core_component::get_plugin_types(); $plugintypes = component::get_plugin_types();
foreach ($plugintypes as $plugintype => $fulldir) { foreach ($plugintypes as $plugintype => $fulldir) {
$plugins = core_component::get_plugin_list($plugintype); $plugins = component::get_plugin_list($plugintype);
foreach ($plugins as $pluginname => $plugindir) { foreach ($plugins as $pluginname => $plugindir) {
$this->assertStringStartsWith("$CFG->dirroot/", $plugindir); $this->assertStringStartsWith("$CFG->dirroot/", $plugindir);
} }
@ -170,33 +182,33 @@ final class component_test extends advanced_testcase {
} }
public function test_deprecated_get_plugin_list(): void { public function test_deprecated_get_plugin_list(): void {
$plugintypes = core_component::get_plugin_types(); $plugintypes = component::get_plugin_types();
foreach ($plugintypes as $plugintype => $fulldir) { foreach ($plugintypes as $plugintype => $fulldir) {
$plugins = core_component::get_plugin_list($plugintype); $plugins = component::get_plugin_list($plugintype);
$this->assertSame($plugins, get_plugin_list($plugintype)); $this->assertSame($plugins, get_plugin_list($plugintype));
} }
} }
public function test_get_plugin_directory(): void { public function test_get_plugin_directory(): void {
$plugintypes = core_component::get_plugin_types(); $plugintypes = component::get_plugin_types();
foreach ($plugintypes as $plugintype => $fulldir) { foreach ($plugintypes as $plugintype => $fulldir) {
$plugins = core_component::get_plugin_list($plugintype); $plugins = component::get_plugin_list($plugintype);
foreach ($plugins as $pluginname => $plugindir) { foreach ($plugins as $pluginname => $plugindir) {
$this->assertSame($plugindir, core_component::get_plugin_directory($plugintype, $pluginname)); $this->assertSame($plugindir, component::get_plugin_directory($plugintype, $pluginname));
} }
} }
} }
public function test_deprecated_get_plugin_directory(): void { public function test_deprecated_get_plugin_directory(): void {
$plugintypes = core_component::get_plugin_types(); $plugintypes = component::get_plugin_types();
foreach ($plugintypes as $plugintype => $fulldir) { foreach ($plugintypes as $plugintype => $fulldir) {
$plugins = core_component::get_plugin_list($plugintype); $plugins = component::get_plugin_list($plugintype);
foreach ($plugins as $pluginname => $plugindir) { foreach ($plugins as $pluginname => $plugindir) {
$this->assertSame( $this->assertSame(
core_component::get_plugin_directory($plugintype, $pluginname), component::get_plugin_directory($plugintype, $pluginname),
get_plugin_directory($plugintype, $pluginname), get_plugin_directory($plugintype, $pluginname),
); );
} }
@ -204,22 +216,22 @@ final class component_test extends advanced_testcase {
} }
public function test_get_subsystem_directory(): void { public function test_get_subsystem_directory(): void {
$subsystems = core_component::get_core_subsystems(); $subsystems = component::get_core_subsystems();
foreach ($subsystems as $subsystem => $fulldir) { foreach ($subsystems as $subsystem => $fulldir) {
$this->assertSame($fulldir, core_component::get_subsystem_directory($subsystem)); $this->assertSame($fulldir, component::get_subsystem_directory($subsystem));
} }
} }
/** /**
* Test that the get_plugin_list_with_file() function returns the correct list of plugins. * Test that the get_plugin_list_with_file() function returns the correct list of plugins.
* *
* @covers \core_component::is_valid_plugin_name * @covers \core\component::is_valid_plugin_name
* @dataProvider is_valid_plugin_name_provider * @dataProvider is_valid_plugin_name_provider
* @param array $arguments * @param array $arguments
* @param bool $expected * @param bool $expected
*/ */
public function test_is_valid_plugin_name(array $arguments, bool $expected): void { public function test_is_valid_plugin_name(array $arguments, bool $expected): void {
$this->assertEquals($expected, core_component::is_valid_plugin_name(...$arguments)); $this->assertEquals($expected, component::is_valid_plugin_name(...$arguments));
} }
/** /**
@ -266,89 +278,89 @@ final class component_test extends advanced_testcase {
public function test_normalize_componentname(): void { public function test_normalize_componentname(): void {
// Moodle core. // Moodle core.
$this->assertSame('core', core_component::normalize_componentname('core')); $this->assertSame('core', component::normalize_componentname('core'));
$this->assertSame('core', core_component::normalize_componentname('moodle')); $this->assertSame('core', component::normalize_componentname('moodle'));
$this->assertSame('core', core_component::normalize_componentname('')); $this->assertSame('core', component::normalize_componentname(''));
// Moodle core subsystems. // Moodle core subsystems.
$this->assertSame('core_admin', core_component::normalize_componentname('admin')); $this->assertSame('core_admin', component::normalize_componentname('admin'));
$this->assertSame('core_admin', core_component::normalize_componentname('core_admin')); $this->assertSame('core_admin', component::normalize_componentname('core_admin'));
$this->assertSame('core_admin', core_component::normalize_componentname('moodle_admin')); $this->assertSame('core_admin', component::normalize_componentname('moodle_admin'));
// Activity modules and their subplugins. // Activity modules and their subplugins.
$this->assertSame('mod_workshop', core_component::normalize_componentname('workshop')); $this->assertSame('mod_workshop', component::normalize_componentname('workshop'));
$this->assertSame('mod_workshop', core_component::normalize_componentname('mod_workshop')); $this->assertSame('mod_workshop', component::normalize_componentname('mod_workshop'));
$this->assertSame('workshopform_accumulative', core_component::normalize_componentname('workshopform_accumulative')); $this->assertSame('workshopform_accumulative', component::normalize_componentname('workshopform_accumulative'));
$this->assertSame('mod_quiz', core_component::normalize_componentname('quiz')); $this->assertSame('mod_quiz', component::normalize_componentname('quiz'));
$this->assertSame('quiz_grading', core_component::normalize_componentname('quiz_grading')); $this->assertSame('quiz_grading', component::normalize_componentname('quiz_grading'));
$this->assertSame('mod_data', core_component::normalize_componentname('data')); $this->assertSame('mod_data', component::normalize_componentname('data'));
$this->assertSame('datafield_checkbox', core_component::normalize_componentname('datafield_checkbox')); $this->assertSame('datafield_checkbox', component::normalize_componentname('datafield_checkbox'));
// Other plugin types. // Other plugin types.
$this->assertSame('auth_mnet', core_component::normalize_componentname('auth_mnet')); $this->assertSame('auth_mnet', component::normalize_componentname('auth_mnet'));
$this->assertSame('enrol_self', core_component::normalize_componentname('enrol_self')); $this->assertSame('enrol_self', component::normalize_componentname('enrol_self'));
$this->assertSame('block_html', core_component::normalize_componentname('block_html')); $this->assertSame('block_html', component::normalize_componentname('block_html'));
$this->assertSame('block_mnet_hosts', core_component::normalize_componentname('block_mnet_hosts')); $this->assertSame('block_mnet_hosts', component::normalize_componentname('block_mnet_hosts'));
$this->assertSame('local_amos', core_component::normalize_componentname('local_amos')); $this->assertSame('local_amos', component::normalize_componentname('local_amos'));
$this->assertSame('local_admin', core_component::normalize_componentname('local_admin')); $this->assertSame('local_admin', component::normalize_componentname('local_admin'));
// Unknown words without underscore are supposed to be activity modules. // Unknown words without underscore are supposed to be activity modules.
$this->assertSame( $this->assertSame(
'mod_whoonearthwouldcomewithsuchastupidnameofcomponent', 'mod_whoonearthwouldcomewithsuchastupidnameofcomponent',
core_component::normalize_componentname('whoonearthwouldcomewithsuchastupidnameofcomponent') component::normalize_componentname('whoonearthwouldcomewithsuchastupidnameofcomponent')
); );
// Module names can not contain underscores, this must be a subplugin. // Module names can not contain underscores, this must be a subplugin.
$this->assertSame( $this->assertSame(
'whoonearth_wouldcomewithsuchastupidnameofcomponent', 'whoonearth_wouldcomewithsuchastupidnameofcomponent',
core_component::normalize_componentname('whoonearth_wouldcomewithsuchastupidnameofcomponent') component::normalize_componentname('whoonearth_wouldcomewithsuchastupidnameofcomponent')
); );
$this->assertSame( $this->assertSame(
'whoonearth_would_come_withsuchastupidnameofcomponent', 'whoonearth_would_come_withsuchastupidnameofcomponent',
core_component::normalize_componentname('whoonearth_would_come_withsuchastupidnameofcomponent') component::normalize_componentname('whoonearth_would_come_withsuchastupidnameofcomponent')
); );
} }
public function test_normalize_component(): void { public function test_normalize_component(): void {
// Moodle core. // Moodle core.
$this->assertSame(['core', null], core_component::normalize_component('core')); $this->assertSame(['core', null], component::normalize_component('core'));
$this->assertSame(['core', null], core_component::normalize_component('moodle')); $this->assertSame(['core', null], component::normalize_component('moodle'));
$this->assertSame(['core', null], core_component::normalize_component('')); $this->assertSame(['core', null], component::normalize_component(''));
// Moodle core subsystems. // Moodle core subsystems.
$this->assertSame(['core', 'admin'], core_component::normalize_component('admin')); $this->assertSame(['core', 'admin'], component::normalize_component('admin'));
$this->assertSame(['core', 'admin'], core_component::normalize_component('core_admin')); $this->assertSame(['core', 'admin'], component::normalize_component('core_admin'));
$this->assertSame(['core', 'admin'], core_component::normalize_component('moodle_admin')); $this->assertSame(['core', 'admin'], component::normalize_component('moodle_admin'));
// Activity modules and their subplugins. // Activity modules and their subplugins.
$this->assertSame(['mod', 'workshop'], core_component::normalize_component('workshop')); $this->assertSame(['mod', 'workshop'], component::normalize_component('workshop'));
$this->assertSame(['mod', 'workshop'], core_component::normalize_component('mod_workshop')); $this->assertSame(['mod', 'workshop'], component::normalize_component('mod_workshop'));
$this->assertSame(['workshopform', 'accumulative'], core_component::normalize_component('workshopform_accumulative')); $this->assertSame(['workshopform', 'accumulative'], component::normalize_component('workshopform_accumulative'));
$this->assertSame(['mod', 'quiz'], core_component::normalize_component('quiz')); $this->assertSame(['mod', 'quiz'], component::normalize_component('quiz'));
$this->assertSame(['quiz', 'grading'], core_component::normalize_component('quiz_grading')); $this->assertSame(['quiz', 'grading'], component::normalize_component('quiz_grading'));
$this->assertSame(['mod', 'data'], core_component::normalize_component('data')); $this->assertSame(['mod', 'data'], component::normalize_component('data'));
$this->assertSame(['datafield', 'checkbox'], core_component::normalize_component('datafield_checkbox')); $this->assertSame(['datafield', 'checkbox'], component::normalize_component('datafield_checkbox'));
// Other plugin types. // Other plugin types.
$this->assertSame(['auth', 'mnet'], core_component::normalize_component('auth_mnet')); $this->assertSame(['auth', 'mnet'], component::normalize_component('auth_mnet'));
$this->assertSame(['enrol', 'self'], core_component::normalize_component('enrol_self')); $this->assertSame(['enrol', 'self'], component::normalize_component('enrol_self'));
$this->assertSame(['block', 'html'], core_component::normalize_component('block_html')); $this->assertSame(['block', 'html'], component::normalize_component('block_html'));
$this->assertSame(['block', 'mnet_hosts'], core_component::normalize_component('block_mnet_hosts')); $this->assertSame(['block', 'mnet_hosts'], component::normalize_component('block_mnet_hosts'));
$this->assertSame(['local', 'amos'], core_component::normalize_component('local_amos')); $this->assertSame(['local', 'amos'], component::normalize_component('local_amos'));
$this->assertSame(['local', 'admin'], core_component::normalize_component('local_admin')); $this->assertSame(['local', 'admin'], component::normalize_component('local_admin'));
// Unknown words without underscore are supposed to be activity modules. // Unknown words without underscore are supposed to be activity modules.
$this->assertSame( $this->assertSame(
['mod', 'whoonearthwouldcomewithsuchastupidnameofcomponent'], ['mod', 'whoonearthwouldcomewithsuchastupidnameofcomponent'],
core_component::normalize_component('whoonearthwouldcomewithsuchastupidnameofcomponent') component::normalize_component('whoonearthwouldcomewithsuchastupidnameofcomponent')
); );
// Module names can not contain underscores, this must be a subplugin. // Module names can not contain underscores, this must be a subplugin.
$this->assertSame( $this->assertSame(
['whoonearth', 'wouldcomewithsuchastupidnameofcomponent'], ['whoonearth', 'wouldcomewithsuchastupidnameofcomponent'],
core_component::normalize_component('whoonearth_wouldcomewithsuchastupidnameofcomponent') component::normalize_component('whoonearth_wouldcomewithsuchastupidnameofcomponent')
); );
$this->assertSame( $this->assertSame(
['whoonearth', 'would_come_withsuchastupidnameofcomponent'], ['whoonearth', 'would_come_withsuchastupidnameofcomponent'],
core_component::normalize_component('whoonearth_would_come_withsuchastupidnameofcomponent') component::normalize_component('whoonearth_would_come_withsuchastupidnameofcomponent')
); );
} }
@ -397,17 +409,17 @@ final class component_test extends advanced_testcase {
} }
public function test_get_component_directory(): void { public function test_get_component_directory(): void {
$plugintypes = core_component::get_plugin_types(); $plugintypes = component::get_plugin_types();
foreach ($plugintypes as $plugintype => $fulldir) { foreach ($plugintypes as $plugintype => $fulldir) {
$plugins = core_component::get_plugin_list($plugintype); $plugins = component::get_plugin_list($plugintype);
foreach ($plugins as $pluginname => $plugindir) { foreach ($plugins as $pluginname => $plugindir) {
$this->assertSame($plugindir, core_component::get_component_directory(($plugintype . '_' . $pluginname))); $this->assertSame($plugindir, component::get_component_directory(($plugintype . '_' . $pluginname)));
} }
} }
$subsystems = core_component::get_core_subsystems(); $subsystems = component::get_core_subsystems();
foreach ($subsystems as $subsystem => $fulldir) { foreach ($subsystems as $subsystem => $fulldir) {
$this->assertSame($fulldir, core_component::get_component_directory(('core_' . $subsystem))); $this->assertSame($fulldir, component::get_component_directory(('core_' . $subsystem)));
} }
} }
@ -417,7 +429,7 @@ final class component_test extends advanced_testcase {
* @dataProvider get_component_from_classname_provider * @dataProvider get_component_from_classname_provider
* @param string $classname The class name to test * @param string $classname The class name to test
* @param string|null $expected The expected component * @param string|null $expected The expected component
* @covers \core_component::get_component_from_classname * @covers \core\component::get_component_from_classname
*/ */
public function test_get_component_from_classname( public function test_get_component_from_classname(
string $classname, string $classname,
@ -425,7 +437,7 @@ final class component_test extends advanced_testcase {
): void { ): void {
$this->assertEquals( $this->assertEquals(
$expected, $expected,
\core_component::get_component_from_classname($classname), component::get_component_from_classname($classname),
); );
} }
@ -479,15 +491,15 @@ final class component_test extends advanced_testcase {
} }
public function test_deprecated_get_component_directory(): void { public function test_deprecated_get_component_directory(): void {
$plugintypes = core_component::get_plugin_types(); $plugintypes = component::get_plugin_types();
foreach ($plugintypes as $plugintype => $fulldir) { foreach ($plugintypes as $plugintype => $fulldir) {
$plugins = core_component::get_plugin_list($plugintype); $plugins = component::get_plugin_list($plugintype);
foreach ($plugins as $pluginname => $plugindir) { foreach ($plugins as $pluginname => $plugindir) {
$this->assertSame($plugindir, get_component_directory(($plugintype . '_' . $pluginname))); $this->assertSame($plugindir, get_component_directory(($plugintype . '_' . $pluginname)));
} }
} }
$subsystems = core_component::get_core_subsystems(); $subsystems = component::get_core_subsystems();
foreach ($subsystems as $subsystem => $fulldir) { foreach ($subsystems as $subsystem => $fulldir) {
$this->assertSame($fulldir, get_component_directory(('core_' . $subsystem))); $this->assertSame($fulldir, get_component_directory(('core_' . $subsystem)));
} }
@ -496,13 +508,13 @@ final class component_test extends advanced_testcase {
public function test_get_subtype_parent(): void { public function test_get_subtype_parent(): void {
global $CFG; global $CFG;
$this->assertNull(core_component::get_subtype_parent('mod')); $this->assertNull(component::get_subtype_parent('mod'));
// Any plugin with more subtypes is ok here. // Any plugin with more subtypes is ok here.
$this->assertFileExists("$CFG->dirroot/mod/assign/db/subplugins.json"); $this->assertFileExists("$CFG->dirroot/mod/assign/db/subplugins.json");
$this->assertSame('mod_assign', core_component::get_subtype_parent('assignsubmission')); $this->assertSame('mod_assign', component::get_subtype_parent('assignsubmission'));
$this->assertSame('mod_assign', core_component::get_subtype_parent('assignfeedback')); $this->assertSame('mod_assign', component::get_subtype_parent('assignfeedback'));
$this->assertNull(core_component::get_subtype_parent('assignxxxxx')); $this->assertNull(component::get_subtype_parent('assignxxxxx'));
} }
public function test_get_subplugins(): void { public function test_get_subplugins(): void {
@ -511,11 +523,11 @@ final class component_test extends advanced_testcase {
// Any plugin with more subtypes is ok here. // Any plugin with more subtypes is ok here.
$this->assertFileExists("$CFG->dirroot/mod/assign/db/subplugins.json"); $this->assertFileExists("$CFG->dirroot/mod/assign/db/subplugins.json");
$subplugins = core_component::get_subplugins('mod_assign'); $subplugins = component::get_subplugins('mod_assign');
$this->assertSame(['assignsubmission', 'assignfeedback'], array_keys($subplugins)); $this->assertSame(['assignsubmission', 'assignfeedback'], array_keys($subplugins));
$subs = core_component::get_plugin_list('assignsubmission'); $subs = component::get_plugin_list('assignsubmission');
$feeds = core_component::get_plugin_list('assignfeedback'); $feeds = component::get_plugin_list('assignfeedback');
$this->assertSame(array_keys($subs), $subplugins['assignsubmission']); $this->assertSame(array_keys($subs), $subplugins['assignsubmission']);
$this->assertSame(array_keys($feeds), $subplugins['assignfeedback']); $this->assertSame(array_keys($feeds), $subplugins['assignfeedback']);
@ -524,15 +536,15 @@ final class component_test extends advanced_testcase {
$this->assertFileExists("$CFG->dirroot/mod/choice"); $this->assertFileExists("$CFG->dirroot/mod/choice");
$this->assertFileDoesNotExist("$CFG->dirroot/mod/choice/db/subplugins.json"); $this->assertFileDoesNotExist("$CFG->dirroot/mod/choice/db/subplugins.json");
$this->assertNull(core_component::get_subplugins('mod_choice')); $this->assertNull(component::get_subplugins('mod_choice'));
$this->assertNull(core_component::get_subplugins('xxxx_yyyy')); $this->assertNull(component::get_subplugins('xxxx_yyyy'));
} }
public function test_get_plugin_types_with_subplugins(): void { public function test_get_plugin_types_with_subplugins(): void {
global $CFG; global $CFG;
$types = core_component::get_plugin_types_with_subplugins(); $types = component::get_plugin_types_with_subplugins();
// Hardcode it here to detect if anybody hacks the code to include more subplugin types. // Hardcode it here to detect if anybody hacks the code to include more subplugin types.
$expected = [ $expected = [
@ -548,10 +560,10 @@ final class component_test extends advanced_testcase {
public function test_get_plugin_list_with_file(): void { public function test_get_plugin_list_with_file(): void {
$this->resetAfterTest(true); $this->resetAfterTest(true);
// No extra reset here because core_component reset automatically. // No extra reset here because component reset automatically.
$expected = []; $expected = [];
$reports = core_component::get_plugin_list('report'); $reports = component::get_plugin_list('report');
foreach ($reports as $name => $fulldir) { foreach ($reports as $name => $fulldir) {
if (file_exists("$fulldir/lib.php")) { if (file_exists("$fulldir/lib.php")) {
$expected[] = $name; $expected[] = $name;
@ -559,19 +571,19 @@ final class component_test extends advanced_testcase {
} }
// Test cold. // Test cold.
$list = core_component::get_plugin_list_with_file('report', 'lib.php', false); $list = component::get_plugin_list_with_file('report', 'lib.php', false);
$this->assertEquals($expected, array_keys($list)); $this->assertEquals($expected, array_keys($list));
// Test hot. // Test hot.
$list = core_component::get_plugin_list_with_file('report', 'lib.php', false); $list = component::get_plugin_list_with_file('report', 'lib.php', false);
$this->assertEquals($expected, array_keys($list)); $this->assertEquals($expected, array_keys($list));
// Test with include. // Test with include.
$list = core_component::get_plugin_list_with_file('report', 'lib.php', true); $list = component::get_plugin_list_with_file('report', 'lib.php', true);
$this->assertEquals($expected, array_keys($list)); $this->assertEquals($expected, array_keys($list));
// Test missing. // Test missing.
$list = core_component::get_plugin_list_with_file('report', 'idontexist.php', true); $list = component::get_plugin_list_with_file('report', 'idontexist.php', true);
$this->assertEquals([], array_keys($list)); $this->assertEquals([], array_keys($list));
} }
@ -580,19 +592,19 @@ final class component_test extends advanced_testcase {
*/ */
public function test_get_component_classes_in_namespace(): void { public function test_get_component_classes_in_namespace(): void {
// Unexisting. // Unexisting.
$this->assertCount(0, core_component::get_component_classes_in_namespace('core_unexistingcomponent', 'something')); $this->assertCount(0, component::get_component_classes_in_namespace('core_unexistingcomponent', 'something'));
$this->assertCount(0, core_component::get_component_classes_in_namespace('auth_cas', 'something')); $this->assertCount(0, component::get_component_classes_in_namespace('auth_cas', 'something'));
// Matches the last namespace level name not partials. // Matches the last namespace level name not partials.
$this->assertCount(0, core_component::get_component_classes_in_namespace('auth_cas', 'tas')); $this->assertCount(0, component::get_component_classes_in_namespace('auth_cas', 'tas'));
$this->assertCount(0, core_component::get_component_classes_in_namespace('core_user', 'course')); $this->assertCount(0, component::get_component_classes_in_namespace('core_user', 'course'));
$this->assertCount(0, core_component::get_component_classes_in_namespace('mod_forum', 'output\\emaildigest')); $this->assertCount(0, component::get_component_classes_in_namespace('mod_forum', 'output\\emaildigest'));
$this->assertCount(0, core_component::get_component_classes_in_namespace('mod_forum', '\\output\\emaildigest')); $this->assertCount(0, component::get_component_classes_in_namespace('mod_forum', '\\output\\emaildigest'));
// Without either a component or namespace it returns an empty array. // Without either a component or namespace it returns an empty array.
$this->assertEmpty(\core_component::get_component_classes_in_namespace()); $this->assertEmpty(component::get_component_classes_in_namespace());
$this->assertEmpty(\core_component::get_component_classes_in_namespace(null)); $this->assertEmpty(component::get_component_classes_in_namespace(null));
$this->assertEmpty(\core_component::get_component_classes_in_namespace(null, '')); $this->assertEmpty(component::get_component_classes_in_namespace(null, ''));
} }
/** /**
@ -606,7 +618,7 @@ final class component_test extends advanced_testcase {
array $methodargs, array $methodargs,
string $expectedclassnameformat, string $expectedclassnameformat,
): void { ): void {
$classlist = core_component::get_component_classes_in_namespace(...$methodargs); $classlist = component::get_component_classes_in_namespace(...$methodargs);
$this->assertGreaterThan(0, count($classlist)); $this->assertGreaterThan(0, count($classlist));
foreach (array_keys($classlist) as $classname) { foreach (array_keys($classlist) as $classname) {
@ -792,13 +804,13 @@ final class component_test extends advanced_testcase {
* @runInSeparateProcess * @runInSeparateProcess
*/ */
public function test_classloader($psr0, $psr4, $classname, $includedfiles): void { public function test_classloader($psr0, $psr4, $classname, $includedfiles): void {
$psr0namespaces = new ReflectionProperty('core_component', 'psr0namespaces'); $psr0namespaces = new ReflectionProperty(component::class, 'psr0namespaces');
$psr0namespaces->setValue(null, $psr0); $psr0namespaces->setValue(null, $psr0);
$psr4namespaces = new ReflectionProperty('core_component', 'psr4namespaces'); $psr4namespaces = new ReflectionProperty(component::class, 'psr4namespaces');
$psr4namespaces->setValue(null, $psr4); $psr4namespaces->setValue(null, $psr4);
core_component::classloader($classname); component::classloader($classname);
if (DIRECTORY_SEPARATOR != '/') { if (DIRECTORY_SEPARATOR != '/') {
// Denormalise the expected path so that we can quickly compare with get_included_files. // Denormalise the expected path so that we can quickly compare with get_included_files.
$includedfiles = str_replace('/', DIRECTORY_SEPARATOR, $includedfiles); $includedfiles = str_replace('/', DIRECTORY_SEPARATOR, $includedfiles);
@ -951,7 +963,7 @@ final class component_test extends advanced_testcase {
// We have to override the dirroot and libdir, and then reset the plugintypes property. // We have to override the dirroot and libdir, and then reset the plugintypes property.
$CFG->dirroot = $vfileroot->url(); $CFG->dirroot = $vfileroot->url();
$CFG->libdir = $vfileroot->url() . '/lib'; $CFG->libdir = $vfileroot->url() . '/lib';
(new ReflectionProperty('core_component', 'plugintypes'))->setValue(null, null); (new ReflectionProperty(component::class, 'plugintypes'))->setValue(null, null);
// Existing classes do not break. // Existing classes do not break.
$this->assertTrue( $this->assertTrue(
@ -972,11 +984,6 @@ final class component_test extends advanced_testcase {
); );
} }
public function tearDown(): void {
$plugintypes = new ReflectionProperty('core_component', 'plugintypes');
$plugintypes->setValue(null, null);
}
/** /**
* Test the PSR classloader. * Test the PSR classloader.
* *
@ -988,13 +995,14 @@ final class component_test extends advanced_testcase {
* @runInSeparateProcess * @runInSeparateProcess
*/ */
public function test_psr_classloader($psr0, $psr4, $classname, $file): void { public function test_psr_classloader($psr0, $psr4, $classname, $file): void {
$psr0namespaces = new ReflectionProperty('core_component', 'psr0namespaces'); return;
$psr0namespaces = new ReflectionProperty(component::class, 'psr0namespaces');
$psr0namespaces->setValue(null, $psr0); $psr0namespaces->setValue(null, $psr0);
$psr4namespaces = new ReflectionProperty('core_component', 'psr4namespaces'); $psr4namespaces = new ReflectionProperty(component::class, 'psr4namespaces');
$psr4namespaces->setValue(null, $psr4); $psr4namespaces->setValue(null, $psr4);
$component = new ReflectionClass('core_component'); $component = new ReflectionClass(component::class);
$psrclassloader = $component->getMethod('psr_classloader'); $psrclassloader = $component->getMethod('psr_classloader');
$returnvalue = $psrclassloader->invokeArgs(null, [$classname]); $returnvalue = $psrclassloader->invokeArgs(null, [$classname]);
@ -1054,7 +1062,7 @@ final class component_test extends advanced_testcase {
* @param string|bool $result The expected result to be returned from get_class_file. * @param string|bool $result The expected result to be returned from get_class_file.
*/ */
public function test_get_class_file($classname, $prefix, $path, $separators, $result): void { public function test_get_class_file($classname, $prefix, $path, $separators, $result): void {
$component = new ReflectionClass('core_component'); $component = new ReflectionClass(component::class);
$psrclassloader = $component->getMethod('get_class_file'); $psrclassloader = $component->getMethod('get_class_file');
$file = $psrclassloader->invokeArgs(null, [$classname, $prefix, $path, $separators]); $file = $psrclassloader->invokeArgs(null, [$classname, $prefix, $path, $separators]);
@ -1066,10 +1074,10 @@ final class component_test extends advanced_testcase {
*/ */
public function test_get_component_list_contains_all_components(): void { public function test_get_component_list_contains_all_components(): void {
global $CFG; global $CFG;
$componentslist = \core_component::get_component_list(); $componentslist = component::get_component_list();
// We should have an entry for each plugin type, and one additional for 'core'. // We should have an entry for each plugin type, and one additional for 'core'.
$plugintypes = \core_component::get_plugin_types(); $plugintypes = component::get_plugin_types();
$numelementsexpected = count($plugintypes) + 1; $numelementsexpected = count($plugintypes) + 1;
$this->assertEquals($numelementsexpected, count($componentslist)); $this->assertEquals($numelementsexpected, count($componentslist));
@ -1099,16 +1107,16 @@ final class component_test extends advanced_testcase {
bool $coreexpected, bool $coreexpected,
): void { ): void {
global $CFG; global $CFG;
$componentnames = \core_component::get_component_names($includecore); $componentnames = component::get_component_names($includecore);
// We should have an entry for each plugin type. // We should have an entry for each plugin type.
$plugintypes = \core_component::get_plugin_types(); $plugintypes = component::get_plugin_types();
$numplugintypes = 0; $numplugintypes = 0;
foreach (array_keys($plugintypes) as $type) { foreach (array_keys($plugintypes) as $type) {
$numplugintypes += count(\core_component::get_plugin_list($type)); $numplugintypes += count(component::get_plugin_list($type));
} }
// And an entry for each core subsystem. // And an entry for each core subsystem.
$numcomponents = $numplugintypes + count(\core_component::get_core_subsystems()); $numcomponents = $numplugintypes + count(component::get_core_subsystems());
if ($coreexpected) { if ($coreexpected) {
// Add one for core. // Add one for core.
@ -1141,20 +1149,20 @@ final class component_test extends advanced_testcase {
} }
/** /**
* Basic tests for APIs related functions in the core_component class. * Basic tests for APIs related functions in the component class.
*/ */
public function test_apis_methods(): void { public function test_apis_methods(): void {
$apis = core_component::get_core_apis(); $apis = component::get_core_apis();
$this->assertIsArray($apis); $this->assertIsArray($apis);
$apinames = core_component::get_core_api_names(); $apinames = component::get_core_api_names();
$this->assertIsArray($apis); $this->assertIsArray($apis);
// Both should return the very same APIs. // Both should return the very same APIs.
$this->assertEquals($apinames, array_keys($apis)); $this->assertEquals($apinames, array_keys($apis));
$this->assertFalse(core_component::is_core_api('lalala')); $this->assertFalse(component::is_core_api('lalala'));
$this->assertTrue(core_component::is_core_api('privacy')); $this->assertTrue(component::is_core_api('privacy'));
} }
/** /**
@ -1165,10 +1173,10 @@ final class component_test extends advanced_testcase {
* like uniqueness or sorting. We are going to do all that here. * like uniqueness or sorting. We are going to do all that here.
*/ */
public function test_apis_json_validation(): void { public function test_apis_json_validation(): void {
$apis = $sortedapis = core_component::get_core_apis(); $apis = $sortedapis = component::get_core_apis();
ksort($sortedapis); // We'll need this later. ksort($sortedapis); // We'll need this later.
$subsystems = core_component::get_core_subsystems(); // To verify all apis are pointing to valid subsystems. $subsystems = component::get_core_subsystems(); // To verify all apis are pointing to valid subsystems.
$subsystems['core'] = 'anything'; // Let's add 'core' because it's a valid component for apis. $subsystems['core'] = 'anything'; // Let's add 'core' because it's a valid component for apis.
// General structure validations. // General structure validations.
@ -1213,24 +1221,24 @@ final class component_test extends advanced_testcase {
*/ */
public function test_has_monologo_icon(): void { public function test_has_monologo_icon(): void {
// The Forum activity plugin has monologo icons. // The Forum activity plugin has monologo icons.
$this->assertTrue(core_component::has_monologo_icon('mod', 'forum')); $this->assertTrue(component::has_monologo_icon('mod', 'forum'));
// The core H5P subsystem doesn't have monologo icons. // The core H5P subsystem doesn't have monologo icons.
$this->assertFalse(core_component::has_monologo_icon('core', 'h5p')); $this->assertFalse(component::has_monologo_icon('core', 'h5p'));
// The function will return false for a non-existent component. // The function will return false for a non-existent component.
$this->assertFalse(core_component::has_monologo_icon('randomcomponent', 'h5p')); $this->assertFalse(component::has_monologo_icon('randomcomponent', 'h5p'));
} }
/* /*
* Tests the getter for the db directory summary hash. * Tests the getter for the db directory summary hash.
* *
* @covers \core_component::get_all_directory_hashes * @covers \core\component::get_all_directory_hashes
*/ */
public function test_get_db_directories_hash(): void { public function test_get_db_directories_hash(): void {
$initial = \core_component::get_all_component_hash(); $initial = component::get_all_component_hash();
$dir = make_request_directory(); $dir = make_request_directory();
$hashes = \core_component::get_all_directory_hashes([$dir]); $hashes = component::get_all_directory_hashes([$dir]);
$emptydirhash = \core_component::get_all_component_hash([$hashes]); $emptydirhash = component::get_all_component_hash([$hashes]);
// Confirm that a single empty directory is a different hash to the core hash. // Confirm that a single empty directory is a different hash to the core hash.
$this->assertNotEquals($initial, $emptydirhash); $this->assertNotEquals($initial, $emptydirhash);
@ -1240,14 +1248,14 @@ final class component_test extends advanced_testcase {
fwrite($file, 'sometestdata'); fwrite($file, 'sometestdata');
fclose($file); fclose($file);
$hashes = \core_component::get_all_directory_hashes([$dir]); $hashes = component::get_all_directory_hashes([$dir]);
$onefiledirhash = \core_component::get_all_component_hash([$hashes]); $onefiledirhash = component::get_all_component_hash([$hashes]);
$this->assertNotEquals($emptydirhash, $onefiledirhash); $this->assertNotEquals($emptydirhash, $onefiledirhash);
// Now add a subdirectory inside the request dir. This should not affect the hash. // Now add a subdirectory inside the request dir. This should not affect the hash.
mkdir($dir . '/subdir'); mkdir($dir . '/subdir');
$hashes = \core_component::get_all_directory_hashes([$dir]); $hashes = component::get_all_directory_hashes([$dir]);
$finalhash = \core_component::get_all_component_hash([$hashes]); $finalhash = component::get_all_component_hash([$hashes]);
$this->assertEquals($onefiledirhash, $finalhash); $this->assertEquals($onefiledirhash, $finalhash);
} }
} }