/**
  * This test the most complex decorator. The aim is to hide users who are in groups that are all hidden
  * and include those who are either in no group at all, or who have a group which is set to display.
  */
 public function test_groupid_attach_countrwapper()
 {
     global $PAGE, $DB;
     $this->setAdminUser();
     // Make basic course submissions. Keep track of which students have what.
     // Make courses.
     $generator = $this->getDataGenerator();
     $coursea = $generator->create_course();
     $courseb = $generator->create_course();
     // Make four students and a teacher.
     $student1a = $generator->create_user();
     $student2a = $generator->create_user();
     $student3b = $generator->create_user();
     $student4b = $generator->create_user();
     $teacher = $generator->create_user();
     // Enrol the users into the courses.
     $studentroleid = $DB->get_field('role', 'id', array('shortname' => 'student'));
     $teacherroleid = $DB->get_field('role', 'id', array('shortname' => 'teacher'));
     $PAGE->set_course($coursea);
     $manager = new course_enrolment_manager($PAGE, $coursea);
     $plugins = $manager->get_enrolment_plugins();
     $instances = $manager->get_enrolment_instances();
     /* @var enrol_manual_plugin $manualenrolplugin */
     $manualenrolplugin = reset($plugins);
     $manualenrolinstance = reset($instances);
     $manualenrolplugin->enrol_user($manualenrolinstance, $student1a->id, $studentroleid);
     $manualenrolplugin->enrol_user($manualenrolinstance, $student2a->id, $studentroleid);
     $manualenrolplugin->enrol_user($manualenrolinstance, $teacher->id, $teacherroleid);
     $PAGE->set_course($courseb);
     $manager = new course_enrolment_manager($PAGE, $courseb);
     $plugins = $manager->get_enrolment_plugins();
     $instances = $manager->get_enrolment_instances();
     $manualenrolplugin = reset($plugins);
     $manualenrolinstance = reset($instances);
     $manualenrolplugin->enrol_user($manualenrolinstance, $student3b->id, $studentroleid);
     $manualenrolplugin->enrol_user($manualenrolinstance, $student4b->id, $studentroleid);
     $manualenrolplugin->enrol_user($manualenrolinstance, $teacher->id, $teacherroleid);
     // Make two groups in each course.
     $group1a = new stdClass();
     $group1a->courseid = $coursea->id;
     $group1a = $generator->create_group($group1a);
     $group2a = new stdClass();
     $group2a->courseid = $coursea->id;
     $group2a = $generator->create_group($group2a);
     $group3b = new stdClass();
     $group3b->courseid = $courseb->id;
     $group3b = $generator->create_group($group3b);
     $group4b = new stdClass();
     $group4b->courseid = $courseb->id;
     $group4b = $generator->create_group($group4b);
     // Make the students into group members.
     // To test all angles:
     // Student 1a is in two groups: 1a and 2a.
     // Student 2a is in 1 group: group 1a.
     // Student 3b is in one group: 3b.
     // Student 4a is in no groups.
     $groupmembership = new stdclass();
     $groupmembership->groupid = $group1a->id;
     $groupmembership->userid = $student1a->id;
     $groupmembership->timeadded = time();
     $DB->insert_record('groups_members', $groupmembership);
     $groupmembership = new stdclass();
     $groupmembership->groupid = $group1a->id;
     $groupmembership->userid = $student2a->id;
     $groupmembership->timeadded = time();
     $DB->insert_record('groups_members', $groupmembership);
     $groupmembership = new stdclass();
     $groupmembership->groupid = $group3b->id;
     $groupmembership->userid = $student3b->id;
     $groupmembership->timeadded = time();
     $DB->insert_record('groups_members', $groupmembership);
     $groupmembership = new stdclass();
     $groupmembership->groupid = $group2a->id;
     $groupmembership->userid = $student1a->id;
     $groupmembership->timeadded = time();
     $DB->insert_record('groups_members', $groupmembership);
     // Make an assignment for each course.
     $assigngenerator = new block_ajax_marking_mod_assign_generator($generator);
     $assignrecord = new stdClass();
     $assignrecord->assessed = 1;
     $assignrecord->scale = 4;
     $assignrecord->course = $coursea->id;
     $assigna = $assigngenerator->create_instance($assignrecord);
     $assignrecord = new stdClass();
     $assignrecord->assessed = 1;
     $assignrecord->scale = 4;
     $assignrecord->course = $courseb->id;
     $assignb = $assigngenerator->create_instance($assignrecord);
     // Make a student submission for each one.
     $submission = new stdClass();
     $submission->userid = $student1a->id;
     $submission->assignment = $assigna->id;
     $assigngenerator->create_assign_submission($submission);
     $submission = new stdClass();
     $submission->userid = $student2a->id;
     $submission->assignment = $assigna->id;
     $assigngenerator->create_assign_submission($submission);
     $submission = new stdClass();
     $submission->userid = $student3b->id;
     $submission->assignment = $assignb->id;
     $assigngenerator->create_assign_submission($submission);
     $submission = new stdClass();
     $submission->userid = $student4b->id;
     $submission->assignment = $assignb->id;
     $assigngenerator->create_assign_submission($submission);
     // A basic query should now return all four submissions.
     $this->setUser($teacher->id);
     // Get coutwrapper without any decorators.
     $nodesbuilder = new ReflectionClass('block_ajax_marking_nodes_builder');
     $moduleunionmethod = $nodesbuilder->getMethod('get_module_queries_array');
     $moduleunionmethod->setAccessible(true);
     $modulequeries = $moduleunionmethod->invoke($nodesbuilder, array());
     $moduleunionmethod = $nodesbuilder->getMethod('get_count_wrapper_query');
     $moduleunionmethod->setAccessible(true);
     /* @var block_ajax_marking_query $countwrapper */
     $countwrapper = $moduleunionmethod->invoke($nodesbuilder, $modulequeries, array());
     $this->assertInstanceOf('block_ajax_marking_query', $countwrapper);
     $totalnumberofsubmissions = 4;
     // Check that the raw countwrapper gets what we need.
     $sql = $countwrapper->debuggable_query();
     $recordset = $DB->get_recordset_sql($countwrapper->get_sql(), $countwrapper->get_params());
     // Count: should be 4. No other 'group by' filters, so just one record with an itemcount for all submissions.
     $pregroupscount = 0;
     $row = $recordset->current();
     $pregroupscount += $row->itemcount;
     $this->assertEquals($totalnumberofsubmissions, $pregroupscount, 'Query not working before we even get to the groups decorator');
     // OK - query works. now get the basic group ids that we expect.
     // Wrap countwrapper in group id decorator.
     $countwrapper = new block_ajax_marking_filter_groupid_attach_countwrapper($countwrapper);
     // Add a select or two so we can see if the groupid is there.
     $countwrapper->add_select(array('table' => 'membergroupquery', 'column' => 'groupid'));
     $countwrapper->add_select(array('table' => 'moduleunion', 'column' => 'userid'), true);
     $countwrapper->add_select(array('table' => 'moduleunion', 'column' => 'coursemoduleid'));
     // For debugging. Stop here and copy this to see what's in the query.
     $wrappedquery = $countwrapper->debuggable_query();
     $results = $countwrapper->execute();
     // Sanity check: we should still get the whole lot before messing with anything.
     $this->assertEquals($totalnumberofsubmissions, count($results), 'Groups decorator has broken the query before any settings changed');
     // Make sure we have the right groups - should be the highest groupid available if they are in more than one
     // group, or the one group id if they are in one group.
     // Student 1a is in two groups. Should be the max id.
     $message = 'Student has the wrong groupid - ' . $results[$student1a->id]->groupid . ' but ought to be the highest out of group1a and group2a ids: ' . $group2a->id;
     $this->assertEquals($group2a->id, $results[$student1a->id]->groupid, $message);
     // Student 2a should be there with the id from group1a. Single group membership.
     $message = 'Student 2a should be in group 1a (id: ' . $group1a->id . ' but is instead in a group with id ' . $results[$student2a->id]->groupid;
     $this->assertEquals($group1a->id, $results[$student2a->id]->groupid, $message);
     // Student 4b has no group, so ought to be without any groupid.
     $message = 'Student 4b should have zero for a groupid due to being in no group, but doesn\'t';
     $this->assertEquals(0, $results[$student4b->id]->groupid, $message);
     // Hide a group2a at coursemoduleid level.
     $newsetting = new stdClass();
     $newsetting->userid = $teacher->id;
     $newsetting->tablename = 'course_modules';
     $newsetting->instanceid = $assigna->cmid;
     $newsetting->display = 1;
     $newsetting->id = $DB->insert_record('block_ajax_marking', $newsetting);
     $newgroupsetting = new stdClass();
     $newgroupsetting->configid = $newsetting->id;
     $newgroupsetting->groupid = $group2a->id;
     $newgroupsetting->display = 0;
     $newgroupsetting->id = $DB->insert_record('block_ajax_marking_groups', $newgroupsetting);
     $results = $countwrapper->execute();
     $message = 'Hiding at coursemodule level has hidden the user instead of used the other available groupid';
     $this->assertArrayHasKey($student1a->id, $results, $message);
     $message = 'Hiding a group at coursemodule level didn\'t work as it ought to have made the student ' . 'in multiple groups who previously had a high id have a low id.';
     $this->assertEquals($group1a->id, $results[$student1a->id]->groupid, $message);
     // Now hide the only group a student is in and verify that we have that student hidden.
     $newgroupsetting = new stdClass();
     $newgroupsetting->configid = $newsetting->id;
     $newgroupsetting->groupid = $group1a->id;
     $newgroupsetting->display = 0;
     $newgroupsetting->id = $DB->insert_record('block_ajax_marking_groups', $newgroupsetting);
     $results = $countwrapper->execute();
     $message = 'Hiding group 1a failed to leave student 2a with a null groupid';
     $this->assertArrayNotHasKey($student2a->id, $results, $message);
     $message = 'Hiding group 1a failed to leave student 1a with a null groupid';
     $this->assertArrayNotHasKey($student1a->id, $results, $message);
     // Hide both groups group at course level.
     // Clean out the settings first.
     $DB->delete_records('block_ajax_marking_groups');
     $DB->delete_records('block_ajax_marking');
     // Test for non-group users coming up as 0.
 }
 /**
  * This tests the function that takes a load of coursemodule nodes, then attaches the groups and each group's
  * current display status.
  *
  * Need to test:
  * - Get the groups that are there
  * - Group to have display 1 if no settings
  * - Group to have display 1/0 at course level with no coursemodule level setting
  *- Group to have 1/0 at coursemodule level if set, regardless of the course level setting.
  */
 public function test_attach_groups_to_coursemodule_nodes()
 {
     global $USER, $DB;
     // The setUp() leaves us with 10 users and two teachers in one course.
     // Make two coursemodules.
     /* @var phpunit_module_generator $assigngenerator */
     $generator = $this->getDataGenerator();
     $assigngenerator = new block_ajax_marking_mod_assign_generator($generator);
     $assignrecord = new stdClass();
     $assignrecord->assessed = 1;
     $assignrecord->scale = 4;
     $assignrecord->course = $this->course->id;
     $assign1 = $assigngenerator->create_instance($assignrecord);
     $assignrecord = new stdClass();
     $assignrecord->assessed = 1;
     $assignrecord->scale = 4;
     $assignrecord->course = $this->course->id;
     $assign2 = $assigngenerator->create_instance($assignrecord);
     // Make two groups.
     $protptypegroup = new stdClass();
     $protptypegroup->courseid = $this->course->id;
     $group1 = $generator->create_group($protptypegroup);
     $protptypegroup = new stdClass();
     $protptypegroup->courseid = $this->course->id;
     $group2 = $generator->create_group($protptypegroup);
     // Make some fake nodes.
     $nodeswithgroups = array();
     $node = new stdClass();
     $node->coursemoduleid = $assign1->cmid;
     $nodeswithgroups[$assign1->cmid] = $node;
     $node = new stdClass();
     $node->coursemoduleid = $assign2->cmid;
     $nodeswithgroups[$assign2->cmid] = $node;
     // Test that we get the groups. All should have display = 1.
     $class = new ReflectionClass('block_ajax_marking_nodes_builder');
     $method = $class->getMethod('attach_groups_to_coursemodule_nodes');
     $method->setAccessible(true);
     $nodeswithgroups = $method->invokeArgs($class, array($nodeswithgroups));
     $this->assertEquals(2, count($nodeswithgroups));
     $this->assertEquals(2, count($nodeswithgroups[$assign1->cmid]->groups));
     $this->assertEquals(2, count($nodeswithgroups[$assign2->cmid]->groups));
     $this->assertArrayHasKey($group1->id, $nodeswithgroups[$assign1->id]->groups);
     $this->assertArrayHasKey($group2->id, $nodeswithgroups[$assign1->id]->groups);
     $this->assertEquals(1, $nodeswithgroups[$assign1->id]->groups[$group1->id]->display);
     $this->assertEquals(1, $nodeswithgroups[$assign1->id]->groups[$group2->id]->display);
     // Hide one group at course level.
     $coursesetting = new stdClass();
     $coursesetting->userid = $USER->id;
     $coursesetting->tablename = 'course';
     $coursesetting->instanceid = $this->course->id;
     $coursesetting->display = 1;
     $coursesetting->groupsdisplay = 1;
     $coursesetting->showorphans = 1;
     $coursesetting->id = $DB->insert_record('block_ajax_marking', $coursesetting);
     $groupsetting = new stdClass();
     $groupsetting->configid = $coursesetting->id;
     $groupsetting->groupid = $group1->id;
     $groupsetting->display = 0;
     $groupsetting->id = $DB->insert_record('block_ajax_marking_groups', $groupsetting);
     // Make some fake nodes.
     $nodescoursehidden = array();
     $node = new stdClass();
     $node->coursemoduleid = $assign1->cmid;
     $nodescoursemodulehidden[$assign1->cmid] = $node;
     $node = new stdClass();
     $node->coursemoduleid = $assign2->cmid;
     $nodescoursemodulehidden[$assign2->cmid] = $node;
     $nodescoursemodulehidden = $method->invokeArgs($class, array($nodescoursemodulehidden));
     $this->assertEquals(2, count($nodescoursemodulehidden));
     $message = 'Wrong number of groups';
     $this->assertEquals(2, count($nodescoursemodulehidden[$assign1->cmid]->groups), $message);
     $this->assertEquals(2, count($nodescoursemodulehidden[$assign2->cmid]->groups), $message);
     $this->assertArrayHasKey($group1->id, $nodescoursemodulehidden[$assign1->id]->groups);
     $this->assertArrayHasKey($group2->id, $nodescoursemodulehidden[$assign1->id]->groups);
     $message = 'Display should be 0 after group was hidden at course level';
     $this->assertEquals(0, $nodescoursemodulehidden[$assign1->id]->groups[$group1->id]->display, $message);
     $this->assertEquals(1, $nodescoursemodulehidden[$assign1->id]->groups[$group2->id]->display);
     // Now try hiding at course module level.
     $coursemodulesetting = new stdClass();
     $coursemodulesetting->userid = $USER->id;
     $coursemodulesetting->tablename = 'course_modules';
     $coursemodulesetting->instanceid = $assign1->cmid;
     $coursemodulesetting->display = 1;
     $coursemodulesetting->groupsdisplay = 1;
     $coursemodulesetting->showorphans = 1;
     $coursemodulesetting->id = $DB->insert_record('block_ajax_marking', $coursemodulesetting);
     $groupsetting = new stdClass();
     $groupsetting->configid = $coursemodulesetting->id;
     $groupsetting->groupid = $group1->id;
     $groupsetting->display = 1;
     $groupsetting->id = $DB->insert_record('block_ajax_marking_groups', $groupsetting);
     // Make some fake nodes.
     $nodescoursemodulehidden = array();
     $node = new stdClass();
     $node->coursemoduleid = $assign1->cmid;
     $nodescoursehidden[$assign1->cmid] = $node;
     $node = new stdClass();
     $node->coursemoduleid = $assign2->cmid;
     $nodescoursehidden[$assign2->cmid] = $node;
     $nodescoursehidden = $method->invokeArgs($class, array($nodescoursehidden));
     // Now, group 1 should be hidden for assign 2 (no override), but visible for assign 1.
     $this->assertEquals(2, count($nodescoursehidden));
     $message = 'Wrong number of groups';
     $this->assertEquals(2, count($nodescoursehidden[$assign1->cmid]->groups), $message);
     $this->assertEquals(2, count($nodescoursehidden[$assign2->cmid]->groups), $message);
     $this->assertArrayHasKey($group1->id, $nodescoursehidden[$assign1->id]->groups);
     $this->assertArrayHasKey($group2->id, $nodescoursehidden[$assign1->id]->groups);
     $message = 'Display should be 1 after group was made visible at course module level';
     $this->assertEquals(1, $nodescoursehidden[$assign1->id]->groups[$group1->id]->display, $message);
     $this->assertEquals(0, $nodescoursehidden[$assign2->id]->groups[$group1->id]->display);
 }