diff --git a/grade/report/user/lib.php b/grade/report/user/lib.php index 1058c07f70559..77fa303ee75ca 100644 --- a/grade/report/user/lib.php +++ b/grade/report/user/lib.php @@ -219,7 +219,14 @@ public function __construct($courseid, $gpr, $context, $userid) { $this->calculate_averages(); } + /** + * Recurses through a tree of elements setting the rowspan property on each element + * + * @param array $element Either the top element or, during recursion, the current element + * @return int The number of elements processed + */ function inject_rowspans(&$element) { + if ($element['depth'] > $this->maxdepth) { $this->maxdepth = $element['depth']; } @@ -227,9 +234,11 @@ function inject_rowspans(&$element) { return 1; } $count = 1; + foreach ($element['children'] as $key=>$child) { $count += $this->inject_rowspans($element['children'][$key]); } + $element['rowspan'] = $count; return $count; } diff --git a/grade/tests/reportuser_test.php b/grade/tests/reportuser_test.php new file mode 100644 index 0000000000000..79530c4eb088a --- /dev/null +++ b/grade/tests/reportuser_test.php @@ -0,0 +1,184 @@ +. + +/** + * Unit tests for grade/report/user/lib.php. + * + * @package core_grade + * @category phpunit + * @copyright 2012 Andrew Davis + * @license http://www.gnu.org/copyleft/gpl.html GNU Public License + */ + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; +require_once($CFG->dirroot.'/grade/lib.php'); +require_once($CFG->dirroot.'/grade/report/user/lib.php'); + + +/** + * Tests grade_report_user (the gradebook's user report) + */ +class gradereportuserlib_testcase extends advanced_testcase { + + /** + * Tests grade_report_user::inject_rowspans() + * + * inject_rowspans() returns the count of the number of elements, sets maxdepth on the + * report object and sets the rowspan property on any element that has children. + */ + public function test_inject_rowspans() { + global $CFG, $USER, $DB; + + parent::setUp(); + $this->resetAfterTest(true); + + $CFG->enableavailability = 1; + $CFG->enablecompletion = 1; + + // Create a course. + $course = $this->getDataGenerator()->create_course(); + $coursecategory = grade_category::fetch_course_category($course->id); + $coursecontext = context_course::instance($course->id); + + // Create and enrol test users. + $student = $this->getDataGenerator()->create_user(array('username' => 'Student Sam')); + $role = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST); + $this->getDataGenerator()->enrol_user($student->id, $course->id, $role->id); + + $teacher = $this->getDataGenerator()->create_user(array('username' => 'Teacher T')); + $role = $DB->get_record('role', array('shortname' => 'editingteacher'), '*', MUST_EXIST); + $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $role->id); + + // An array so we can test with both users in a loop. + $users = array($student, $teacher); + + // Make the student the current user. + $this->setUser($student); + + // Test an empty course. + $report = $this->create_report($course, $student, $coursecontext); + // a lead column that spans all children + course grade item = 2 + $this->assertEquals(2, $report->inject_rowspans($report->gtree->top_element)); + $this->assertEquals(2, $report->gtree->top_element['rowspan']); + $this->assertEquals(2, $report->maxdepth); + + // Only elements with children should have rowspan set. + if (array_key_exists('rowspan', $report->gtree->top_element['children'][1])) { + $this->fail('Elements without children should not have rowspan set'); + } + + // Add 2 activities. + $data1 = $this->getDataGenerator()->create_module('data', array('assessed' => 1, 'scale' => 100, 'course' => $course->id)); + + $forum1 = $this->getDataGenerator()->create_module('forum', array('assessed' => 1, 'scale' => 100, 'course' => $course->id)); + $forum1cm = get_coursemodule_from_id('forum', $forum1->cmid); + // Switch the stdClass instance for a grade item instance so grade_item::set_parent() is available. + $forum1 = grade_item::fetch(array('itemtype' => 'mod', 'itemmodule' => 'forum', 'iteminstance' => $forum1->id, 'courseid' => $course->id)); + + $report = $this->create_report($course, $student, $coursecontext); + // Lead column + course + (2 x activity) = 4 + $this->assertEquals(4, $report->inject_rowspans($report->gtree->top_element)); + $this->assertEquals(4, $report->gtree->top_element['rowspan']); + // Lead column + 1 level (course + 2 activities) = 2 + $this->assertEquals(2, $report->maxdepth); + + // Only elements with children should have rowspan set. + if (array_key_exists('rowspan', $report->gtree->top_element['children'][1])) { + $this->fail('Elements without children should not have rowspan set'); + } + + // Hide the forum activity. + set_coursemodule_visible($forum1cm->id, 0); + + foreach ($users as $user) { + + $this->setUser($user); + $message = 'Testing with ' . $user->username; + accesslib_clear_all_caches_for_unit_testing(); + + $report = $this->create_report($course, $user, $coursecontext); + // Lead column + course + (2 x activity) = 4 (element count isn't affected by hiding) + $this->assertEquals(4, $report->inject_rowspans($report->gtree->top_element), $message); + $this->assertEquals(4, $report->gtree->top_element['rowspan'], $message); + // Lead column -> 1 level containing the course + 2 activities = 2 + $this->assertEquals(2, $report->maxdepth, $message); + } + + // Unhide the forum activity. + set_coursemodule_visible($forum1cm->id, 1); + + // Create a category and put the forum in it. + $params = new stdClass(); + $params->courseid = $course->id; + $params->fullname = 'unittestcategory'; + $params->parent = $coursecategory->id; + $gradecategory = new grade_category($params, false); + $gradecategory->insert(); + + $forum1->set_parent($gradecategory->id); + + $report = $this->create_report($course, $student, $coursecontext); + // Lead column + course + (category + category grade item) + (2 x activity) = 6 + $this->assertEquals(6, $report->inject_rowspans($report->gtree->top_element)); + $this->assertEquals(6, $report->gtree->top_element['rowspan']); + // Lead column -> the category -> the forum activity = 3 + $this->assertEquals(3, $report->maxdepth); + + // Check rowspan on the category. The category itself + category grade item + forum = 3 + $this->assertEquals(3, $report->gtree->top_element['children'][4]['rowspan']); + // check the forum doesn't have rowspan set + if (array_key_exists('rowspan', $report->gtree->top_element['children'][4]['children'][3])) { + $this->fail('The forum has no children so should not have rowspan set'); + } + + // Conditional activity tests. + $DB->insert_record('course_modules_availability', (object)array( + 'coursemoduleid'=>$forum1cm->id, + 'gradeitemid' => 37, + 'grademin' => 5.5 + )); + + $cm = (object)array('id' => $forum1cm->id); + $test = new condition_info($cm, CONDITION_MISSING_EVERYTHING); + $fullcm = $test->get_full_course_module(); + + foreach ($users as $user) { + + $this->setUser($user); + $message = 'Testing with ' . $user->username; + accesslib_clear_all_caches_for_unit_testing(); + + $report = $this->create_report($course, $user, $coursecontext); + // Lead column + course + (category + category grade item) + (2 x activity) = 6 + $this->assertEquals(6, $report->inject_rowspans($report->gtree->top_element), $message); + $this->assertEquals(6, $report->gtree->top_element['rowspan'], $message); + // Lead column -> the category -> the forum activity = 3 + $this->assertEquals(3, $report->maxdepth, $message); + } + } + + private function create_report($course, $user, $coursecontext) { + + $gpr = new grade_plugin_return(array('type' => 'report', 'plugin'=>'user', 'courseid' => $course->id, 'userid' => $user->id)); + $report = new grade_report_user($course->id, $gpr, $coursecontext, $user->id); + + return $report; + } + +} +