public function test_group_members_only()
 {
     global $CFG;
     $this->setAdminUser();
     $this->create_extra_users();
     $CFG->enableavailability = true;
     $grouping = $this->getDataGenerator()->create_grouping(array('courseid' => $this->course->id));
     groups_assign_grouping($grouping->id, $this->groups[0]->id);
     // Force create an assignment with SEPARATEGROUPS.
     $instance = $this->getDataGenerator()->create_module('assign', array('course' => $this->course->id), array('availability' => json_encode(\core_availability\tree::get_root_json(array(\availability_grouping\condition::get_json()))), 'groupingid' => $grouping->id));
     $cm = get_coursemodule_from_instance('assign', $instance->id);
     $context = context_module::instance($cm->id);
     $assign = new testable_assign($context, $cm, $this->course);
     $this->setUser($this->teachers[0]);
     get_fast_modinfo($this->course, 0, true);
     $this->assertCount(5, $assign->list_participants(0, true));
 }
Example #2
0
 /**
  * Tests user restrictions, as they affect lists of users returned by
  * core API functions.
  *
  * This includes the groupingid option (when group mode is in use), and
  * standard activity restrictions using the availability API.
  */
 public function test_user_restrictions()
 {
     global $DB, $CFG;
     $this->resetAfterTest();
     // Use existing sample course from setUp.
     $courseid = $this->workshop->course->id;
     // Make a test grouping and two groups.
     $generator = $this->getDataGenerator();
     $grouping = $generator->create_grouping(array('courseid' => $courseid));
     $group1 = $generator->create_group(array('courseid' => $courseid));
     groups_assign_grouping($grouping->id, $group1->id);
     $group2 = $generator->create_group(array('courseid' => $courseid));
     groups_assign_grouping($grouping->id, $group2->id);
     // Group 3 is not in the grouping.
     $group3 = $generator->create_group(array('courseid' => $courseid));
     // Enrol some students.
     $roleids = $DB->get_records_menu('role', null, '', 'shortname, id');
     $student1 = $generator->create_user();
     $student2 = $generator->create_user();
     $student3 = $generator->create_user();
     $generator->enrol_user($student1->id, $courseid, $roleids['student']);
     $generator->enrol_user($student2->id, $courseid, $roleids['student']);
     $generator->enrol_user($student3->id, $courseid, $roleids['student']);
     // Place students in groups (except student 3).
     groups_add_member($group1, $student1);
     groups_add_member($group2, $student2);
     groups_add_member($group3, $student3);
     // The existing workshop doesn't have any restrictions, so user lists
     // should include all three users.
     $allusers = get_enrolled_users(context_course::instance($courseid));
     $result = $this->workshop->get_grouped($allusers);
     $this->assertCount(4, $result);
     $users = array_keys($result[0]);
     sort($users);
     $this->assertEquals(array($student1->id, $student2->id, $student3->id), $users);
     $this->assertEquals(array($student1->id), array_keys($result[$group1->id]));
     $this->assertEquals(array($student2->id), array_keys($result[$group2->id]));
     $this->assertEquals(array($student3->id), array_keys($result[$group3->id]));
     // Test get_users_with_capability_sql (via get_potential_authors).
     $users = $this->workshop->get_potential_authors(false);
     $this->assertCount(3, $users);
     $users = $this->workshop->get_potential_authors(false, $group2->id);
     $this->assertEquals(array($student2->id), array_keys($users));
     // Create another test workshop with grouping set.
     $workshopitem = $this->getDataGenerator()->create_module('workshop', array('course' => $courseid, 'groupmode' => SEPARATEGROUPS, 'groupingid' => $grouping->id));
     $cm = get_coursemodule_from_instance('workshop', $workshopitem->id, $courseid, false, MUST_EXIST);
     $workshopgrouping = new testable_workshop($workshopitem, $cm, $this->workshop->course);
     // This time the result should only include users and groups in the
     // selected grouping.
     $result = $workshopgrouping->get_grouped($allusers);
     $this->assertCount(3, $result);
     $users = array_keys($result[0]);
     sort($users);
     $this->assertEquals(array($student1->id, $student2->id), $users);
     $this->assertEquals(array($student1->id), array_keys($result[$group1->id]));
     $this->assertEquals(array($student2->id), array_keys($result[$group2->id]));
     // Test get_users_with_capability_sql (via get_potential_authors).
     $users = $workshopgrouping->get_potential_authors(false);
     $userids = array_keys($users);
     sort($userids);
     $this->assertEquals(array($student1->id, $student2->id), $userids);
     $users = $workshopgrouping->get_potential_authors(false, $group2->id);
     $this->assertEquals(array($student2->id), array_keys($users));
     // Enable the availability system and create another test workshop with
     // availability restriction on grouping.
     $CFG->enableavailability = true;
     $workshopitem = $this->getDataGenerator()->create_module('workshop', array('course' => $courseid, 'availability' => json_encode(\core_availability\tree::get_root_json(array(\availability_grouping\condition::get_json($grouping->id)), \core_availability\tree::OP_AND, false))));
     $cm = get_coursemodule_from_instance('workshop', $workshopitem->id, $courseid, false, MUST_EXIST);
     $workshoprestricted = new testable_workshop($workshopitem, $cm, $this->workshop->course);
     // The get_grouped function isn't intended to apply this restriction,
     // so it should be the same as the base workshop. (Note: in reality,
     // get_grouped is always run with the parameter being the result of
     // one of the get_potential_xxx functions, so it works.)
     $result = $workshoprestricted->get_grouped($allusers);
     $this->assertCount(4, $result);
     $this->assertCount(3, $result[0]);
     // The get_users_with_capability_sql-based functions should apply it.
     $users = $workshoprestricted->get_potential_authors(false);
     $userids = array_keys($users);
     sort($userids);
     $this->assertEquals(array($student1->id, $student2->id), $userids);
     $users = $workshoprestricted->get_potential_authors(false, $group2->id);
     $this->assertEquals(array($student2->id), array_keys($users));
 }
 /**
  * Sets the value(s) of an availability element.
  *
  * At present this only supports the following value 'Grouping: xxx' where
  * xxx is the name of a grouping. Additional value types can be added as
  * necessary.
  *
  * @param string $value Value code
  * @return void
  */
 public function set_value($value)
 {
     global $DB;
     $driver = $this->session->getDriver();
     // Check the availability condition is currently unset - we don't yet
     // support changing an existing one.
     $existing = $this->get_value();
     if ($existing && $existing !== '{"op":"&","c":[],"showc":[]}') {
         throw new Exception('Cannot automatically set availability when ' . 'there is existing setting - must clear manually');
     }
     // Check the value matches a supported format.
     $matches = array();
     if (!preg_match('~^\\s*([^:]*):\\s*(.*?)\\s*$~', $value, $matches)) {
         throw new Exception('Value for availability field does not match correct ' . 'format. Example: "Grouping: G1"');
     }
     $type = $matches[1];
     $param = $matches[2];
     if ($this->running_javascript()) {
         switch (strtolower($type)) {
             case 'grouping':
                 // Set a grouping condition.
                 $driver->click('//div[@class="availability-button"]/button');
                 $driver->click('//button[@id="availability_addrestriction_grouping"]');
                 $escparam = $this->session->getSelectorsHandler()->xpathLiteral($param);
                 $nodes = $driver->find('//span[contains(concat(" " , @class, " "), " availability_grouping ")]//' . 'option[normalize-space(.) = ' . $escparam . ']');
                 if (count($nodes) != 1) {
                     throw new Exception('Cannot find grouping in dropdown' . count($nodes));
                 }
                 $node = reset($nodes);
                 $value = $node->getValue();
                 $driver->selectOption('//span[contains(concat(" " , @class, " "), " availability_grouping ")]//' . 'select', $value);
                 break;
             default:
                 // We don't support other types yet. The test author must write
                 // manual 'click on that button, etc' commands.
                 throw new Exception('The availability type "' . $type . '" is currently not supported - must set manually');
         }
     } else {
         $courseid = $driver->getValue('//input[@name="course"]');
         switch (strtolower($type)) {
             case 'grouping':
                 // Define result with one grouping condition.
                 $groupingid = $DB->get_field('groupings', 'id', array('courseid' => $courseid, 'name' => $param));
                 $json = \core_availability\tree::get_root_json(array(\availability_grouping\condition::get_json($groupingid)));
                 break;
             default:
                 // We don't support other types yet.
                 throw new Exception('The availability type "' . $type . '" is currently not supported - must set with JavaScript');
         }
         $driver->setValue('//textarea[@name="availabilityconditionsjson"]', json_encode($json));
     }
 }
 /**
  * Tests the filter_users (bulk checking) function.
  */
 public function test_filter_users()
 {
     global $DB, $CFG;
     $this->resetAfterTest();
     $CFG->enableavailability = true;
     // Erase static cache before test.
     condition::wipe_static_cache();
     // Make a test course and some users.
     $generator = $this->getDataGenerator();
     $course = $generator->create_course();
     $roleids = $DB->get_records_menu('role', null, '', 'shortname, id');
     $teacher = $generator->create_user();
     $generator->enrol_user($teacher->id, $course->id, $roleids['teacher']);
     $allusers = array($teacher->id => $teacher);
     $students = array();
     for ($i = 0; $i < 3; $i++) {
         $student = $generator->create_user();
         $students[$i] = $student;
         $generator->enrol_user($student->id, $course->id, $roleids['student']);
         $allusers[$student->id] = $student;
     }
     $info = new \core_availability\mock_info($course);
     $checker = new \core_availability\capability_checker($info->get_context());
     // Make test groups.
     $group1 = $generator->create_group(array('courseid' => $course->id));
     $group2 = $generator->create_group(array('courseid' => $course->id));
     $grouping1 = $generator->create_grouping(array('courseid' => $course->id));
     $grouping2 = $generator->create_grouping(array('courseid' => $course->id));
     groups_assign_grouping($grouping1->id, $group1->id);
     groups_assign_grouping($grouping2->id, $group2->id);
     // Make page in grouping 2.
     $pagegen = $generator->get_plugin_generator('mod_page');
     $page = $pagegen->create_instance(array('course' => $course->id, 'groupingid' => $grouping2->id, 'availability' => '{"op":"|","show":true,"c":[{"type":"grouping","activity":true}]}'));
     // Assign students to groups as follows (teacher is not in a group):
     // 0: no groups.
     // 1: in group 1/grouping 1.
     // 2: in group 2/grouping 2.
     groups_add_member($group1, $students[1]);
     groups_add_member($group2, $students[2]);
     // Test specific grouping.
     $cond = new condition((object) array('id' => (int) $grouping1->id));
     $result = array_keys($cond->filter_user_list($allusers, false, $info, $checker));
     ksort($result);
     $this->assertEquals(array($teacher->id, $students[1]->id), $result);
     $result = array_keys($cond->filter_user_list($allusers, true, $info, $checker));
     ksort($result);
     $this->assertEquals(array($teacher->id, $students[0]->id, $students[2]->id), $result);
     // Test course-module grouping.
     $modinfo = get_fast_modinfo($course);
     $cm = $modinfo->get_cm($page->cmid);
     $info = new \core_availability\info_module($cm);
     $result = array_keys($info->filter_user_list($allusers, $course));
     $this->assertEquals(array($teacher->id, $students[2]->id), $result);
 }
Example #5
0
 /**
  * Tests the behaviour of the counter in unique_sql_parameter().
  *
  * There was a problem with static counters used to implement a sequence of
  * parameter placeholders (MDL-53481). As always with static variables, it
  * is a bit tricky to unit test the behaviour reliably as it depends on the
  * actual tests executed and also their order.
  *
  * To minimise risk of false expected behaviour, this test method should be
  * first one where {@link core_availability\tree::get_user_list_sql()} is
  * used. We also use higher number of condition instances to increase the
  * risk of the counter collision, should there remain a problem.
  */
 public function test_unique_sql_parameter_behaviour()
 {
     global $DB;
     $this->resetAfterTest();
     $generator = $this->getDataGenerator();
     // Create a test course with multiple groupings and groups and a student in each of them.
     $course = $generator->create_course();
     $user = $generator->create_user();
     $studentroleid = $DB->get_field('role', 'id', array('shortname' => 'student'));
     $generator->enrol_user($user->id, $course->id, $studentroleid);
     // The total number of groupings and groups must not be greater than 61.
     // There is a limit in MySQL on the max number of joined tables.
     $groups = [];
     for ($i = 0; $i < 25; $i++) {
         $group = $generator->create_group(array('courseid' => $course->id));
         groups_add_member($group, $user);
         $groups[] = $group;
     }
     $groupings = [];
     for ($i = 0; $i < 25; $i++) {
         $groupings[] = $generator->create_grouping(array('courseid' => $course->id));
     }
     foreach ($groupings as $grouping) {
         foreach ($groups as $group) {
             groups_assign_grouping($grouping->id, $group->id);
         }
     }
     $info = new \core_availability\mock_info($course);
     // Make a huge tree with 'AND' of all groups and groupings conditions.
     $conditions = [];
     foreach ($groups as $group) {
         $conditions[] = \availability_group\condition::get_json($group->id);
     }
     foreach ($groupings as $groupingid) {
         $conditions[] = \availability_grouping\condition::get_json($grouping->id);
     }
     shuffle($conditions);
     $tree = new tree(tree::get_root_json($conditions));
     list($sql, $params) = $tree->get_user_list_sql(false, $info, false);
     // This must not throw exception.
     $DB->fix_sql_params($sql, $params);
 }