MDL-83888 course: grade activity overview item

The course activity overview tablew now shows the grade items for the
activity if the user has grading.
This commit is contained in:
ferran
2025-03-04 12:29:16 +01:00
parent f92afcee5c
commit d6a8068cd1
3 changed files with 257 additions and 0 deletions
@@ -23,6 +23,8 @@ use core_courseformat\local\overview\overviewitem;
use core_courseformat\output\local\overview\activityname;
use core_courseformat\output\local\overview\overviewpage;
use core_courseformat\base as courseformat;
use grade_item;
use grade_grade;
/**
* Base class for activity overview.
@@ -170,4 +172,87 @@ abstract class activityoverviewbase {
content: $completion,
);
}
/**
* Retrieves the grades overview items for the activity.
*
* Most activities will have none or one grade. However, some activities
* may have multiple grades, such as workshop or quiz.
*
* It is not recommended to override this method unless the plugin
* has specific requirements. Instead, plugins should override
* get_grade_item_names to provide the grade item names.
*
* @return overviewitem[] Array of overview items representing the grades.
*/
public function get_grades_overviews(): array {
global $CFG, $USER;
// This overview is to see the own grades, users with full gradebook
// access will see all grades in the gradebook.
if (has_capability('moodle/grade:viewall', $this->context)) {
return [];
}
if (!plugin_supports('mod', $this->cm->modname, FEATURE_GRADE_HAS_GRADE, false)) {
return [];
}
require_once($CFG->libdir . '/gradelib.php');
$items = grade_item::fetch_all([
'itemtype' => 'mod',
'itemmodule' => $this->cm->modname,
'iteminstance' => $this->cm->instance,
'courseid' => $this->course->id,
]);
if (empty($items)) {
return [];
}
$itemnames = $this->get_grade_item_names($items);
$result = [];
foreach ($items as $item) {
// Plugins may decide to hide a specific grade item by not setting a name.
if (empty($itemnames[$item->id])) {
continue;
}
$gradegrade = grade_grade::fetch(['itemid' => $item->id, 'userid' => $USER->id]);
if (
!$gradegrade
|| ($gradegrade->is_hidden() && !has_capability('moodle/grade:viewhidden', $this->context))
) {
$result[] = new overviewitem(
name: $itemnames[$item->id],
value: '-',
content: '-',
);
continue;
}
$result[] = new overviewitem(
name: $itemnames[$item->id],
value: $gradegrade->finalgrade,
content: grade_format_gradevalue($gradegrade->finalgrade, $item),
);
}
return $result;
}
/**
* Retrieves the grade item names for the activity.
*
* By default, the overview will display the grade if the activities
* has only one grade item. The name of the grade item will be 'Grade'.
* For plugins with multiple grade items, the plugin must override this method
* and provide names for each grade item that want to be displayed.
*
* @param grade_item[] $items
* @return array<integer, string> the grade item names indexed by item id.
*/
protected function get_grade_item_names(array $items): array {
if (count($items) == 1) {
return [reset($items)->id => get_string('gradenoun')];
}
return [];
}
}
@@ -226,6 +226,13 @@ class overviewtable implements renderable, named_templatable {
$row = array_merge($row, $overview->get_extra_overview_items($output));
$gradeitems = $overview->get_grades_overviews();
if (!empty($gradeitems)) {
foreach ($gradeitems as $gradeitem) {
$row[$gradeitem->get_name()] = $gradeitem;
}
}
// Actions are always the last column, if any.
$row['actions'] = $overview->get_actions_overview($output);
@@ -31,6 +31,7 @@ final class activityoverviewbase_test extends \advanced_testcase {
global $CFG;
require_once($CFG->libdir . '/completionlib.php');
require_once($CFG->dirroot . '/course/format/tests/fixtures/fake_activityoverview.php');
require_once($CFG->libdir . '/gradelib.php');
parent::setUpBeforeClass();
}
@@ -166,4 +167,168 @@ final class activityoverviewbase_test extends \advanced_testcase {
$this->assertEquals(null, $result->get_value());
$this->assertEquals('-', $result->get_content());
}
/**
* Test get_grades_overviews method.
*
* @covers ::get_grades_overviews
*/
public function test_get_grades_overviews(): void {
$this->resetAfterTest();
$this->setAdminUser();
$generator = $this->getDataGenerator();
$course = $this->getDataGenerator()->create_course();
$teacher = $this->getDataGenerator()->create_and_enrol($course, 'teacher');
$student = $this->getDataGenerator()->create_and_enrol($course, 'student');
// Create some modules.
$assign = $this->getDataGenerator()->create_module(
'assign',
['course' => $course->id]
);
$workshop = $this->getDataGenerator()->create_module(
'workshop',
['course' => $course->id],
['grade' => 100.0],
);
$page = $this->getDataGenerator()->create_module(
'page',
['course' => $course->id]
);
// Assignments have one grade item.
$assignitems = \grade_item::fetch_all([
'itemtype' => 'mod',
'itemmodule' => 'assign',
'iteminstance' => (int) $assign->id,
'courseid' => $course->id,
]);
$gradegrade = new \grade_grade();
$gradegrade->itemid = reset($assignitems)->id;
$gradegrade->userid = (int) $student->id;
$gradegrade->rawgrade = 88;
$gradegrade->finalgrade = 88;
$gradegrade->insert();
// Workshops have two grade items.
$workshopitems = array_values(
\grade_item::fetch_all([
'itemtype' => 'mod',
'itemmodule' => 'workshop',
'iteminstance' => (int) $workshop->id,
'courseid' => $course->id,
['grade' => 100.0],
])
);
$gradegrade = new \grade_grade();
$gradegrade->itemid = reset($workshopitems)->id;
$gradegrade->userid = (int) $student->id;
$gradegrade->rawgrade = 77;
$gradegrade->finalgrade = 77;
$gradegrade->insert();
// Validate student grades.
$this->setUser($student);
$modinfo = get_fast_modinfo($course);
// Validate assign gradeitems.
$cm = $modinfo->get_cm($assign->cmid);
$overview = new \core_courseformat\fake_activityoverview($cm);
$result = $overview->get_grades_overviews();
$this->assertCount(1, $result);
$this->assertEquals(get_string('gradenoun'), $result[0]->get_name());
$this->assertEquals(88, $result[0]->get_value());
$this->assertEquals('88.00', $result[0]->get_content());
// Validate workshop gradeitems (having two grade, they should return an empty array).
$cm = $modinfo->get_cm($workshop->cmid);
$overview = new \core_courseformat\fake_activityoverview($cm);
$result = $overview->get_grades_overviews();
$this->assertEmpty($result);
// Validate page has no gradeitems.
$cm = $modinfo->get_cm($page->cmid);
$overview = new \core_courseformat\fake_activityoverview($cm);
$result = $overview->get_grades_overviews();
$this->assertEmpty($result);
// Validate teacher does not has grade overiviews items.
$this->setUser($teacher);
$modinfo = get_fast_modinfo($course);
// Validate assign gradeitems.
$cm = $modinfo->get_cm($assign->cmid);
$overview = new \core_courseformat\fake_activityoverview($cm);
$result = $overview->get_grades_overviews();
$this->assertEmpty($result);;
// Validate workshop gradeitems (having two grade, they should return an empty array).
$cm = $modinfo->get_cm($workshop->cmid);
$overview = new \core_courseformat\fake_activityoverview($cm);
$result = $overview->get_grades_overviews();
$this->assertEmpty($result);
// Validate page has no gradeitems.
$cm = $modinfo->get_cm($page->cmid);
$overview = new \core_courseformat\fake_activityoverview($cm);
$result = $overview->get_grades_overviews();
$this->assertEmpty($result);
}
/**
* Test get_grades_overviews when the grade item is hidden.
*
* @covers ::get_grades_overviews
*/
/**
* Test get_grades_overviews method.
*
* @covers ::get_grades_overviews
*/
public function test_get_grades_overviews_hidden(): void {
$this->resetAfterTest();
$this->setAdminUser();
$generator = $this->getDataGenerator();
$course = $this->getDataGenerator()->create_course();
$student = $this->getDataGenerator()->create_and_enrol($course, 'student');
// Create some modules.
$assign = $this->getDataGenerator()->create_module(
'assign',
['course' => $course->id]
);
// Assignments have one grade item.
$assignitems = \grade_item::fetch_all([
'itemtype' => 'mod',
'itemmodule' => 'assign',
'iteminstance' => (int) $assign->id,
'courseid' => $course->id,
]);
$gradeitem = reset($assignitems);
$gradegrade = new \grade_grade();
$gradegrade->itemid = $gradeitem->id;
$gradegrade->userid = (int) $student->id;
$gradegrade->rawgrade = 88;
$gradegrade->finalgrade = 88;
$gradegrade->insert();
// Hide some grades.
$gradeitem->set_hidden(1, true);
// Validate student grades.
$this->setUser($student);
$modinfo = get_fast_modinfo($course);
// Validate assign gradeitems.
$cm = $modinfo->get_cm($assign->cmid);
$overview = new \core_courseformat\fake_activityoverview($cm);
$result = $overview->get_grades_overviews();
$this->assertCount(1, $result);
$this->assertEquals(get_string('gradenoun'), $result[0]->get_name());
$this->assertEquals('-', $result[0]->get_value());
$this->assertEquals('-', $result[0]->get_content());
}
}