From 300d2331990ec34ef3881521d20dcb97beef0e43 Mon Sep 17 00:00:00 2001 From: meirzamoodle Date: Wed, 2 Jul 2025 12:13:49 +0700 Subject: [PATCH] MDL-77237 core: Suppress debugging during capabilities cleanup To prevent the debugging messages from appearing during the upgrade, I set a flag to hide them. For the test file, I adjusted the parameters in the unassign_capability() function, which seemed to be using the parameter intended for assign_capability(). --- lib/accesslib.php | 29 ++++++++++++++++++++--------- lib/classes/param.php | 2 +- lib/tests/accesslib_test.php | 28 +++++++++++++++++++++++++--- 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/lib/accesslib.php b/lib/accesslib.php index dc55d7de1c0..3c6df9dfbc5 100644 --- a/lib/accesslib.php +++ b/lib/accesslib.php @@ -1480,13 +1480,14 @@ function assign_capability($capability, $permission, $roleid, $contextid, $overw * @param string $capability the name of the capability * @param int $roleid the role id * @param int|context $contextid null means all contexts + * @param bool $showdebug if true, will show debugging messages * @return boolean true or exception */ -function unassign_capability($capability, $roleid, $contextid = null) { +function unassign_capability($capability, $roleid, $contextid = null, bool $showdebug = true) { global $DB, $USER; // Capability must exist. - if (!$capinfo = get_capability_info($capability)) { + if (!get_capability_info($capability, $showdebug)) { throw new coding_exception("Capability '{$capability}' was not found! This has to be fixed in code."); } @@ -2460,7 +2461,11 @@ function capabilities_cleanup($component, $newcapdef = null) { // Delete from roles. if ($roles = get_roles_with_capability($cachedcap->name)) { foreach ($roles as $role) { - if (!unassign_capability($cachedcap->name, $role->id)) { + if (!unassign_capability( + capability: $cachedcap->name, + roleid: $role->id, + showdebug: false, // Suppress debugging messages in the get_capability_info(). + )) { throw new \moodle_exception('cannotunassigncap', 'error', '', (object)array('cap' => $cachedcap->name, 'role' => $role->name)); } @@ -2595,10 +2600,11 @@ function is_inside_frontpage(context $context) { /** * Returns capability information (cached) * - * @param string $capabilityname + * @param string $capabilityname the capability name. + * @param bool $showdebug if true, will show debugging messages. * @return ?stdClass object or null if capability not found */ -function get_capability_info($capabilityname) { +function get_capability_info(string $capabilityname, bool $showdebug = true): ?stdClass { $caps = get_all_capabilities(); // Check for deprecated capability. @@ -2608,12 +2614,17 @@ function get_capability_info($capabilityname) { if (isset($caps[$deprecatedinfo['replacement']])) { $capabilityname = $deprecatedinfo['replacement']; } else { - debugging("Capability '{$capabilityname}' was supposed to be replaced with ". - "'{$deprecatedinfo['replacement']}', which does not exist !"); + if ($showdebug) { + debugging("Capability '{$capabilityname}' was supposed to be replaced with ". + "'{$deprecatedinfo['replacement']}', which does not exist !"); + } } } - $fullmessage = $deprecatedinfo['fullmessage']; - debugging($fullmessage, DEBUG_DEVELOPER); + + if ($showdebug) { + $fullmessage = $deprecatedinfo['fullmessage']; + debugging($fullmessage, DEBUG_DEVELOPER); + } } if (!isset($caps[$capabilityname])) { return null; diff --git a/lib/classes/param.php b/lib/classes/param.php index e6e564ea5ab..32818dbb915 100644 --- a/lib/classes/param.php +++ b/lib/classes/param.php @@ -1189,7 +1189,7 @@ enum param: string { * @return string */ protected function clean_param_value_capability(mixed $param): string { - if (get_capability_info($param)) { + if (!empty($param) && get_capability_info($param)) { return $param; } else { return ''; diff --git a/lib/tests/accesslib_test.php b/lib/tests/accesslib_test.php index e8b266eefba..3dba63a3d79 100644 --- a/lib/tests/accesslib_test.php +++ b/lib/tests/accesslib_test.php @@ -2248,7 +2248,7 @@ final class accesslib_test extends advanced_testcase { $this->expectException('coding_exception'); $this->expectExceptionMessage("Capability '{$capability}' was not found! This has to be fixed in code."); - unassign_capability($capability, CAP_ALLOW, $teacherrole->id, $coursecontext); + unassign_capability($capability, $teacherrole->id, $coursecontext); } /** @@ -3597,10 +3597,10 @@ final class accesslib_test extends advanced_testcase { $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups')); $this->assertFalse($rc); assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $allroles['teacher'], $frontpagecontext); - unassign_capability('moodle/site:accessallgroups', $allroles['teacher'], $frontpagecontext, true); + unassign_capability('moodle/site:accessallgroups', $allroles['teacher'], $frontpagecontext); $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups')); $this->assertFalse($rc); - unassign_capability('moodle/site:accessallgroups', $allroles['teacher'], $frontpagecontext->id, true); + unassign_capability('moodle/site:accessallgroups', $allroles['teacher'], $frontpagecontext->id); unset($rc); accesslib_clear_all_caches_for_unit_testing(); // Must be done after assign_capability(). @@ -5316,6 +5316,28 @@ final class accesslib_test extends advanced_testcase { $this->assertTrue(has_capability('fake/fullfeatured:fakecapability', \core\context\system::instance(), $user)); $this->assertEquals('Fullfeatured capability description', get_capability_string('fake/fullfeatured:fakecapability')); } + + /** + * Test get_deprecated_capability_info() debugging messages. + * + * @covers ::get_deprecated_capability_info + */ + public function test_get_deprecated_capability_info_debugging(): void { + $this->resetAfterTest(); + $course = $this->getDataGenerator()->create_course(); + $this->getDataGenerator()->create_and_enrol($course); + $this->setup_fake_plugin('access'); + // Debugging messages should not be called with valid capability. + get_capability_info('fake/access:existingcapability'); + $this->assertDebuggingNotCalled(); + // Debugging messages should be called with invalid capability. + get_capability_info('fake/access:fakecapability'); + $this->assertDebuggingCalled("The capability 'fake/access:fakecapability' is" + . " deprecated.This capability should not be used anymore."); + // Debugging messages should not be called with invalid capability with suppression param supplied. + get_capability_info('fake/access:fakecapability', false); + $this->assertDebuggingNotCalled(); + } } /**