MDL-73549 Course: My course page menu improvement

- Introduce core_course_category::get_nearest_editable_subcategory()
 - This function will return the first creatable/manageable category
for current user
 - With this new function, we can fix the issue that the users with
course management or creation permision at category level cannot see
the manage menu on My courses page
This commit is contained in:
Huong Nguyen 2022-03-02 13:16:18 +07:00
parent 1d99ba19a2
commit 481cfdc3f0
6 changed files with 251 additions and 9 deletions

View file

@ -1102,4 +1102,109 @@ class core_course_category_testcase extends advanced_testcase {
$this->assertCount(1, $courses);
$this->assertArrayHasKey($othercourse->id, $courses);
}
/**
* Test get_nearest_editable_subcategory() method.
*
* @covers \core_course_category::get_nearest_editable_subcategory
*/
public function test_get_nearest_editable_subcategory(): void {
global $DB;
$coursecreatorrole = $DB->get_record('role', ['shortname' => 'coursecreator']);
$managerrole = $DB->get_record('role', ['shortname' => 'manager']);
// Create categories.
$category1 = core_course_category::create(['name' => 'Cat1']);
$category2 = core_course_category::create(['name' => 'Cat2']);
$category3 = core_course_category::create(['name' => 'Cat3']);
// Get the category contexts.
$category1context = $category1->get_context();
$category2context = $category2->get_context();
$category3context = $category3->get_context();
// Create user.
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$user3 = $this->getDataGenerator()->create_user();
// Assign the user1 to 'Course creator' role for Cat1.
role_assign($coursecreatorrole->id, $user1->id, $category1context->id);
// Assign the user2 to 'Manager' role for Cat3.
role_assign($managerrole->id, $user2->id, $category3context->id);
// Start scenario 1.
// user3 has no permission to create course or manage category.
$this->setUser($user3);
$coursecat = core_course_category::user_top();
$this->assertEmpty(core_course_category::get_nearest_editable_subcategory($coursecat, ['create']));
$this->assertEmpty(core_course_category::get_nearest_editable_subcategory($coursecat, ['moodle/course:create']));
$this->assertEmpty(core_course_category::get_nearest_editable_subcategory($coursecat, ['manage']));
$this->assertEmpty(core_course_category::get_nearest_editable_subcategory($coursecat, ['moodle/category:manage']));
$this->assertEmpty(core_course_category::get_nearest_editable_subcategory($coursecat, ['create', 'manage']));
// End scenario 1.
// Start scenario 2.
// user1 has permission to create course but has no permission to manage category.
$this->setUser($user1);
$coursecat = core_course_category::user_top();
$this->assertNotEmpty(core_course_category::get_nearest_editable_subcategory($coursecat, ['create']));
$this->assertNotEmpty(core_course_category::get_nearest_editable_subcategory($coursecat, ['moodle/course:create']));
$this->assertEmpty(core_course_category::get_nearest_editable_subcategory($coursecat, ['manage']));
$this->assertEmpty(core_course_category::get_nearest_editable_subcategory($coursecat, ['moodle/category:manage']));
$this->assertEmpty(core_course_category::get_nearest_editable_subcategory($coursecat, ['create', 'manage']));
// The get_nearest_editable_subcategory should return Cat1.
$this->assertEquals($category1->id, core_course_category::get_nearest_editable_subcategory($coursecat, ['create'])->id);
$this->assertEquals($category1->id,
core_course_category::get_nearest_editable_subcategory($coursecat, ['moodle/course:create'])->id);
// Assign the user1 to 'Course creator' role for Cat2.
role_assign($coursecreatorrole->id, $user1->id, $category2context->id);
// The get_nearest_editable_subcategory should still return Cat1 (First creatable subcategory) for create course capability.
$this->assertEquals($category1->id, core_course_category::get_nearest_editable_subcategory($coursecat, ['create'])->id);
$this->assertEquals($category1->id,
core_course_category::get_nearest_editable_subcategory($coursecat, ['moodle/course:create'])->id);
// End scenario 2.
// Start scenario 3.
// user2 has no permission to create course but has permission to manage category.
$this->setUser($user2);
// Remove the moodle/course:create capability for the manager role.
unassign_capability('moodle/course:create', $managerrole->id);
$coursecat = core_course_category::user_top();
$this->assertEmpty(core_course_category::get_nearest_editable_subcategory($coursecat, ['create']));
$this->assertEmpty(core_course_category::get_nearest_editable_subcategory($coursecat, ['moodle/course:create']));
$this->assertNotEmpty(core_course_category::get_nearest_editable_subcategory($coursecat, ['manage']));
$this->assertNotEmpty(core_course_category::get_nearest_editable_subcategory($coursecat, ['moodle/category:manage']));
$this->assertEmpty(core_course_category::get_nearest_editable_subcategory($coursecat, ['create', 'manage']));
// The get_nearest_editable_subcategory should return Cat3.
$this->assertEquals($category3->id, core_course_category::get_nearest_editable_subcategory($coursecat, ['manage'])->id);
$this->assertEquals($category3->id,
core_course_category::get_nearest_editable_subcategory($coursecat, ['moodle/category:manage'])->id);
// End scenario 3.
// Start scenario 4.
// user2 has both permission to create course and manage category.
// Add the moodle/course:create capability back again for the manager role.
assign_capability('moodle/course:create', CAP_ALLOW, $managerrole->id, $category3context->id);
$this->setUser($user2);
$coursecat = core_course_category::user_top();
$this->assertNotEmpty(core_course_category::get_nearest_editable_subcategory($coursecat, ['create']));
$this->assertNotEmpty(core_course_category::get_nearest_editable_subcategory($coursecat, ['moodle/course:create']));
$this->assertNotEmpty(core_course_category::get_nearest_editable_subcategory($coursecat, ['manage']));
$this->assertNotEmpty(core_course_category::get_nearest_editable_subcategory($coursecat, ['moodle/category:manage']));
$this->assertNotEmpty(core_course_category::get_nearest_editable_subcategory($coursecat, ['create', 'manage']));
// The get_nearest_editable_subcategory should return Cat3.
$this->assertEquals($category3->id,
core_course_category::get_nearest_editable_subcategory($coursecat, ['create', 'manage'])->id);
$this->assertEquals($category3->id, core_course_category::get_nearest_editable_subcategory($coursecat,
['moodle/course:create', 'moodle/category:manage'])->id);
// End scenario 4.
// Start scenario 5.
// Exception will be thrown if $permissionstocheck is empty.
$this->setUser($user1);
$coursecat = core_course_category::user_top();
$this->expectException('coding_exception');
$this->expectExceptionMessage('Invalid permissionstocheck parameter');
$this->assertNotEmpty(core_course_category::get_nearest_editable_subcategory($coursecat, []));
// End scenario 5.
}
}