/**
  * Tests the backup and restore of single activity to same course (duplicate)
  * when it contains availability conditions that depend on other items in
  * course.
  */
 public function test_duplicate_availability()
 {
     global $DB, $CFG;
     $this->resetAfterTest(true);
     $this->setAdminUser();
     $CFG->enableavailability = true;
     $CFG->enablecompletion = true;
     // Create a course with completion enabled and 2 forums.
     $generator = $this->getDataGenerator();
     $course = $generator->create_course(array('format' => 'topics', 'enablecompletion' => COMPLETION_ENABLED));
     $forum = $generator->create_module('forum', array('course' => $course->id));
     $forum2 = $generator->create_module('forum', array('course' => $course->id, 'completion' => COMPLETION_TRACKING_MANUAL));
     // We need a grade, easiest is to add an assignment.
     $assignrow = $generator->create_module('assign', array('course' => $course->id));
     $assign = new assign(context_module::instance($assignrow->cmid), false, false);
     $item = $assign->get_grade_item();
     // Make a test group and grouping as well.
     $group = $generator->create_group(array('courseid' => $course->id, 'name' => 'Group!'));
     $grouping = $generator->create_grouping(array('courseid' => $course->id, 'name' => 'Grouping!'));
     // Set the forum to have availability conditions on all those things,
     // plus some that don't exist or are special values.
     $availability = '{"op":"|","show":false,"c":[' . '{"type":"completion","cm":' . $forum2->cmid . ',"e":1},' . '{"type":"completion","cm":99999999,"e":1},' . '{"type":"grade","id":' . $item->id . ',"min":4,"max":94},' . '{"type":"grade","id":99999998,"min":4,"max":94},' . '{"type":"grouping","id":' . $grouping->id . '},' . '{"type":"grouping","id":99999997},' . '{"type":"group","id":' . $group->id . '},' . '{"type":"group"},' . '{"type":"group","id":99999996}' . ']}';
     $DB->set_field('course_modules', 'availability', $availability, array('id' => $forum->cmid));
     // Duplicate it.
     $newcmid = $this->duplicate($course, $forum->cmid);
     // For those which still exist on the course we expect it to keep using
     // the real ID. For those which do not exist on the course any more
     // (e.g. simulating backup/restore of single activity between 2 courses)
     // we expect the IDs to be replaced with marker value: 0 for cmid
     // and grade, -1 for group/grouping.
     $expected = str_replace(array('99999999', '99999998', '99999997', '99999996'), array(0, 0, -1, -1), $availability);
     // Check settings in new activity.
     $actual = $DB->get_field('course_modules', 'availability', array('id' => $newcmid));
     $this->assertEquals($expected, $actual);
 }
示例#2
0
 /**
  * Format a column of data for display
  *
  * @param stdClass $row
  * @return string
  */
 public function col_grademax(stdClass $row)
 {
     $gradeitem = $this->assignment->get_grade_item();
     return format_float($this->assignment->get_instance()->grade, $gradeitem->get_decimals());
 }
示例#3
0
 /**
  * Tests constructing and using grade condition.
  */
 public function test_usage()
 {
     global $USER, $CFG;
     require_once $CFG->dirroot . '/mod/assign/locallib.php';
     $this->resetAfterTest();
     $CFG->enableavailability = true;
     // Make a test course and user.
     $course = $this->getDataGenerator()->create_course();
     $user = $this->getDataGenerator()->create_user();
     $this->getDataGenerator()->enrol_user($user->id, $course->id);
     // Make assign module.
     $assignrow = $this->getDataGenerator()->create_module('assign', array('course' => $course->id, 'name' => 'Test!'));
     $assign = new assign(context_module::instance($assignrow->cmid), false, false);
     $modinfo = get_fast_modinfo($course);
     $cm = $modinfo->get_cm($assignrow->cmid);
     $info = new \core_availability\info_module($cm);
     // Get the actual grade item.
     $item = $assign->get_grade_item();
     // Construct tree with grade condition (any grade, specified item).
     $structure = (object) array('type' => 'grade', 'id' => (int) $item->id);
     $cond = new condition($structure);
     // Check if available (not available).
     $this->assertFalse($cond->is_available(false, $info, true, $user->id));
     $information = $cond->get_description(false, false, $info);
     $this->assertRegExp('~have a grade.*Test!~', $information);
     $this->assertTrue($cond->is_available(true, $info, true, $user->id));
     // Add grade and check available.
     self::set_grade($assignrow, $user->id, 37.2);
     $this->assertTrue($cond->is_available(false, $info, true, $user->id));
     $this->assertFalse($cond->is_available(true, $info, true, $user->id));
     $information = $cond->get_description(false, true, $info);
     $this->assertRegExp('~do not have a grade.*Test!~', $information);
     // Construct directly and test remaining conditions; first, min grade (fail).
     self::set_grade($assignrow, $user->id, 29.99999);
     $structure->min = 30.0;
     $cond = new condition($structure);
     $this->assertFalse($cond->is_available(false, $info, true, $user->id));
     $information = $cond->get_description(false, false, $info);
     $this->assertRegExp('~achieve a required score.*Test!~', $information);
     $this->assertTrue($cond->is_available(true, $info, true, $user->id));
     // Min grade (success).
     self::set_grade($assignrow, $user->id, 30);
     $this->assertTrue($cond->is_available(false, $info, true, $user->id));
     $this->assertFalse($cond->is_available(true, $info, true, $user->id));
     $information = $cond->get_description(false, true, $info);
     $this->assertRegExp('~do not get certain scores.*Test!~', $information);
     // Max grade (fail).
     unset($structure->min);
     $structure->max = 30.0;
     $cond = new condition($structure);
     $this->assertFalse($cond->is_available(false, $info, true, $user->id));
     $information = $cond->get_description(false, false, $info);
     $this->assertRegExp('~get an appropriate score.*Test!~', $information);
     $this->assertTrue($cond->is_available(true, $info, true, $user->id));
     // Max grade (success).
     self::set_grade($assignrow, $user->id, 29.99999);
     $this->assertTrue($cond->is_available(false, $info, true, $user->id));
     $this->assertFalse($cond->is_available(true, $info, true, $user->id));
     $information = $cond->get_description(false, true, $info);
     $this->assertRegExp('~do not get certain scores.*Test!~', $information);
     // Max and min (fail).
     $structure->min = 30.0;
     $structure->max = 34.12345;
     $cond = new condition($structure);
     $this->assertFalse($cond->is_available(false, $info, true, $user->id));
     $information = $cond->get_description(false, false, $info);
     $this->assertRegExp('~get a particular score.*Test!~', $information);
     $this->assertTrue($cond->is_available(true, $info, true, $user->id));
     // Still fail (other end).
     self::set_grade($assignrow, $user->id, 34.12345);
     $this->assertFalse($cond->is_available(false, $info, true, $user->id));
     // Success (top end).
     self::set_grade($assignrow, $user->id, 34.12344);
     $this->assertTrue($cond->is_available(false, $info, true, $user->id));
     $this->assertFalse($cond->is_available(true, $info, true, $user->id));
     $information = $cond->get_description(false, true, $info);
     $this->assertRegExp('~do not get certain scores.*Test!~', $information);
     // Success (bottom end).
     self::set_grade($assignrow, $user->id, 30.0);
     $this->assertTrue($cond->is_available(false, $info, true, $user->id));
     $this->assertFalse($cond->is_available(true, $info, true, $user->id));
     $information = $cond->get_description(false, true, $info);
     $this->assertRegExp('~do not get certain scores.*Test!~', $information);
 }
示例#4
0
 /**
  * Tests the is_available and get_description functions.
  */
 public function test_usage()
 {
     global $CFG, $DB;
     require_once $CFG->dirroot . '/mod/assign/locallib.php';
     $this->resetAfterTest();
     // Create course with completion turned on.
     $CFG->enablecompletion = true;
     $CFG->enableavailability = true;
     $generator = $this->getDataGenerator();
     $course = $generator->create_course(array('enablecompletion' => 1));
     $user = $generator->create_user();
     $generator->enrol_user($user->id, $course->id);
     $this->setUser($user);
     // Create a Page with manual completion for basic checks.
     $page = $generator->get_plugin_generator('mod_page')->create_instance(array('course' => $course->id, 'name' => 'Page!', 'completion' => COMPLETION_TRACKING_MANUAL));
     // Create an assignment - we need to have something that can be graded
     // so as to test the PASS/FAIL states. Set it up to be completed based
     // on its grade item.
     $assignrow = $this->getDataGenerator()->create_module('assign', array('course' => $course->id, 'name' => 'Assign!', 'completion' => COMPLETION_TRACKING_AUTOMATIC));
     $DB->set_field('course_modules', 'completiongradeitemnumber', 0, array('id' => $assignrow->cmid));
     $assign = new assign(context_module::instance($assignrow->cmid), false, false);
     // Get basic details.
     $modinfo = get_fast_modinfo($course);
     $pagecm = $modinfo->get_cm($page->cmid);
     $assigncm = $assign->get_course_module();
     $info = new \core_availability\mock_info($course, $user->id);
     // COMPLETE state (false), positive and NOT.
     $cond = new condition((object) array('cm' => (int) $pagecm->id, 'e' => COMPLETION_COMPLETE));
     $this->assertFalse($cond->is_available(false, $info, true, $user->id));
     $information = $cond->get_description(false, false, $info);
     $information = \core_availability\info::format_info($information, $course);
     $this->assertRegExp('~Page!.*is marked complete~', $information);
     $this->assertTrue($cond->is_available(true, $info, true, $user->id));
     // INCOMPLETE state (true).
     $cond = new condition((object) array('cm' => (int) $pagecm->id, 'e' => COMPLETION_INCOMPLETE));
     $this->assertTrue($cond->is_available(false, $info, true, $user->id));
     $this->assertFalse($cond->is_available(true, $info, true, $user->id));
     $information = $cond->get_description(false, true, $info);
     $information = \core_availability\info::format_info($information, $course);
     $this->assertRegExp('~Page!.*is marked complete~', $information);
     // Mark page complete.
     $completion = new completion_info($course);
     $completion->update_state($pagecm, COMPLETION_COMPLETE);
     // COMPLETE state (true).
     $cond = new condition((object) array('cm' => (int) $pagecm->id, 'e' => COMPLETION_COMPLETE));
     $this->assertTrue($cond->is_available(false, $info, true, $user->id));
     $this->assertFalse($cond->is_available(true, $info, true, $user->id));
     $information = $cond->get_description(false, true, $info);
     $information = \core_availability\info::format_info($information, $course);
     $this->assertRegExp('~Page!.*is incomplete~', $information);
     // INCOMPLETE state (false).
     $cond = new condition((object) array('cm' => (int) $pagecm->id, 'e' => COMPLETION_INCOMPLETE));
     $this->assertFalse($cond->is_available(false, $info, true, $user->id));
     $information = $cond->get_description(false, false, $info);
     $information = \core_availability\info::format_info($information, $course);
     $this->assertRegExp('~Page!.*is incomplete~', $information);
     $this->assertTrue($cond->is_available(true, $info, true, $user->id));
     // We are going to need the grade item so that we can get pass/fails.
     $gradeitem = $assign->get_grade_item();
     grade_object::set_properties($gradeitem, array('gradepass' => 50.0));
     $gradeitem->update();
     // With no grade, it should return true for INCOMPLETE and false for
     // the other three.
     $cond = new condition((object) array('cm' => (int) $assigncm->id, 'e' => COMPLETION_INCOMPLETE));
     $this->assertTrue($cond->is_available(false, $info, true, $user->id));
     $this->assertFalse($cond->is_available(true, $info, true, $user->id));
     $cond = new condition((object) array('cm' => (int) $assigncm->id, 'e' => COMPLETION_COMPLETE));
     $this->assertFalse($cond->is_available(false, $info, true, $user->id));
     $this->assertTrue($cond->is_available(true, $info, true, $user->id));
     // Check $information for COMPLETE_PASS and _FAIL as we haven't yet.
     $cond = new condition((object) array('cm' => (int) $assigncm->id, 'e' => COMPLETION_COMPLETE_PASS));
     $this->assertFalse($cond->is_available(false, $info, true, $user->id));
     $information = $cond->get_description(false, false, $info);
     $information = \core_availability\info::format_info($information, $course);
     $this->assertRegExp('~Assign!.*is complete and passed~', $information);
     $this->assertTrue($cond->is_available(true, $info, true, $user->id));
     $cond = new condition((object) array('cm' => (int) $assigncm->id, 'e' => COMPLETION_COMPLETE_FAIL));
     $this->assertFalse($cond->is_available(false, $info, true, $user->id));
     $information = $cond->get_description(false, false, $info);
     $information = \core_availability\info::format_info($information, $course);
     $this->assertRegExp('~Assign!.*is complete and failed~', $information);
     $this->assertTrue($cond->is_available(true, $info, true, $user->id));
     // Change the grade to be complete and failed.
     self::set_grade($assignrow, $user->id, 40);
     $cond = new condition((object) array('cm' => (int) $assigncm->id, 'e' => COMPLETION_INCOMPLETE));
     $this->assertFalse($cond->is_available(false, $info, true, $user->id));
     $this->assertTrue($cond->is_available(true, $info, true, $user->id));
     $cond = new condition((object) array('cm' => (int) $assigncm->id, 'e' => COMPLETION_COMPLETE));
     $this->assertTrue($cond->is_available(false, $info, true, $user->id));
     $this->assertFalse($cond->is_available(true, $info, true, $user->id));
     $cond = new condition((object) array('cm' => (int) $assigncm->id, 'e' => COMPLETION_COMPLETE_PASS));
     $this->assertFalse($cond->is_available(false, $info, true, $user->id));
     $information = $cond->get_description(false, false, $info);
     $information = \core_availability\info::format_info($information, $course);
     $this->assertRegExp('~Assign!.*is complete and passed~', $information);
     $this->assertTrue($cond->is_available(true, $info, true, $user->id));
     $cond = new condition((object) array('cm' => (int) $assigncm->id, 'e' => COMPLETION_COMPLETE_FAIL));
     $this->assertTrue($cond->is_available(false, $info, true, $user->id));
     $this->assertFalse($cond->is_available(true, $info, true, $user->id));
     $information = $cond->get_description(false, true, $info);
     $information = \core_availability\info::format_info($information, $course);
     $this->assertRegExp('~Assign!.*is not complete and failed~', $information);
     // Now change it to pass.
     self::set_grade($assignrow, $user->id, 60);
     $cond = new condition((object) array('cm' => (int) $assigncm->id, 'e' => COMPLETION_INCOMPLETE));
     $this->assertFalse($cond->is_available(false, $info, true, $user->id));
     $this->assertTrue($cond->is_available(true, $info, true, $user->id));
     $cond = new condition((object) array('cm' => (int) $assigncm->id, 'e' => COMPLETION_COMPLETE));
     $this->assertTrue($cond->is_available(false, $info, true, $user->id));
     $this->assertFalse($cond->is_available(true, $info, true, $user->id));
     $cond = new condition((object) array('cm' => (int) $assigncm->id, 'e' => COMPLETION_COMPLETE_PASS));
     $this->assertTrue($cond->is_available(false, $info, true, $user->id));
     $this->assertFalse($cond->is_available(true, $info, true, $user->id));
     $information = $cond->get_description(false, true, $info);
     $information = \core_availability\info::format_info($information, $course);
     $this->assertRegExp('~Assign!.*is not complete and passed~', $information);
     $cond = new condition((object) array('cm' => (int) $assigncm->id, 'e' => COMPLETION_COMPLETE_FAIL));
     $this->assertFalse($cond->is_available(false, $info, true, $user->id));
     $information = $cond->get_description(false, false, $info);
     $information = \core_availability\info::format_info($information, $course);
     $this->assertRegExp('~Assign!.*is complete and failed~', $information);
     $this->assertTrue($cond->is_available(true, $info, true, $user->id));
     // Simulate deletion of an activity by using an invalid cmid. These
     // conditions always fail, regardless of NOT flag or INCOMPLETE.
     $cond = new condition((object) array('cm' => $assigncm->id + 100, 'e' => COMPLETION_COMPLETE));
     $this->assertFalse($cond->is_available(false, $info, true, $user->id));
     $information = $cond->get_description(false, false, $info);
     $information = \core_availability\info::format_info($information, $course);
     $this->assertRegExp('~(Missing activity).*is marked complete~', $information);
     $this->assertFalse($cond->is_available(true, $info, true, $user->id));
     $cond = new condition((object) array('cm' => $assigncm->id + 100, 'e' => COMPLETION_INCOMPLETE));
     $this->assertFalse($cond->is_available(false, $info, true, $user->id));
 }