diff --git a/lib/accesslib.php b/lib/accesslib.php index 09298458a49..08b08ae6c0e 100644 --- a/lib/accesslib.php +++ b/lib/accesslib.php @@ -2641,7 +2641,13 @@ function get_deprecated_capability_info($capabilityname) { foreach ($allcaps as $cap) { if (!in_array($cap['component'], $components)) { $components[] = $cap['component']; - $defpath = core_component::get_component_directory($cap['component']).'/db/access.php'; + + $componentdir = core_component::get_component_directory($cap['component']); + if ($componentdir === null) { + continue; + } + + $defpath = "{$componentdir}/db/access.php"; if (file_exists($defpath)) { $deprecatedcapabilities = []; require($defpath); diff --git a/lib/tests/accesslib_test.php b/lib/tests/accesslib_test.php index df701bc20cb..a533bbe5289 100644 --- a/lib/tests/accesslib_test.php +++ b/lib/tests/accesslib_test.php @@ -2114,6 +2114,38 @@ class accesslib_test extends advanced_testcase { ]; } + /** + * Test get_deprecated_capability_info() with an invalid component. + * + * @covers get_deprecated_capability_info + */ + public function test_get_deprecated_capability_info_invalid_component(): void { + global $DB; + + $this->resetAfterTest(); + + // Set up a fake plugin. + $this->setup_fake_plugin('access'); + + // Add a plugin for an unrelated fake component. + $DB->insert_record('capabilities', [ + 'name' => 'mod/fake:addinstance', + 'captype' => 'write', + 'contextlevel' => CONTEXT_COURSE, + 'component' => 'mod_fake', + 'riskbitmask' => 4, + ]); + + // Purge the cache. + cache::make('core', 'capabilities')->purge(); + + // For now we have deprecated fake/access:fakecapability. + $this->assertNotEmpty($DB->get_record('capabilities', ['component' => 'mod_fake'])); + $info = get_deprecated_capability_info('fake/access:fakecapability'); + $this->assertIsArray($info); + $this->assertDebuggingNotCalled(); + } + /** * Test that assigning a fake cap does not return. *