Merge branch 'MDL-66147-master' of https://github.com/snake/moodle

This commit is contained in:
Jun Pataleta
2019-08-13 16:34:34 +08:00
12 changed files with 531 additions and 51 deletions
+1
View File
@@ -1639,6 +1639,7 @@ $string['rejectdots'] = 'Reject...';
$string['relativedatesmode'] = 'Relative dates mode';
$string['relativedatesmode_help'] = 'Display course or activity dates relative to the user\'s start date in the course.<br />The user\'s course start date will be their enrolment start date, unless they are enrolled before the course begins in which case their start date will be the course start date.<br/><strong>WARNING: This is an experimental feature and not all activities may support it. Once the course has been created, this course setting can no longer be changed.</strong>';
$string['relativedatesmode_warning'] = '<strong>Warning:</strong> Relative dates mode cannot be changed once the course has been created.';
$string['relativedatestimediffformat'] = '%ad %hh %im';
$string['reload'] = 'Reload';
$string['remoteappuser'] = 'Remote {$a} User';
$string['remove'] = 'Remove';
+23
View File
@@ -2374,6 +2374,29 @@ function usertime($date, $timezone=99) {
return $date - $userdate->getOffset() + $dst;
}
/**
* Get a formatted string representation of an interval between two unix timestamps.
*
* E.g.
* $intervalstring = get_time_interval_string(12345600, 12345660);
* Will produce the string:
* '0d 0h 1m'
*
* @param int $time1 unix timestamp
* @param int $time2 unix timestamp
* @param string $format string (can be lang string) containing format chars: https://www.php.net/manual/en/dateinterval.format.php.
* @return string the formatted string describing the time difference, e.g. '10d 11h 45m'.
*/
function get_time_interval_string(int $time1, int $time2, string $format = ''): string {
$dtdate = new DateTime();
$dtdate->setTimeStamp($time1);
$dtdate2 = new DateTime();
$dtdate2->setTimeStamp($time2);
$interval = $dtdate2->diff($dtdate);
$format = empty($format) ? get_string('relativedatestimediffformat', 'moodle') : $format;
return $interval->format($format);
}
/**
* Given a time, return the GMT timestamp of the most recent midnight
* for the current user.
+79
View File
@@ -4457,4 +4457,83 @@ class core_moodlelib_testcase extends advanced_testcase {
$this->assertContains('passwords cannot be reset on this site', quoted_printable_decode($result[0]->body));
}
/**
* Test the get_time_interval_string for a range of inputs.
*
* @dataProvider get_time_interval_string_provider
* @param int $time1 the time1 param.
* @param int $time2 the time2 param.
* @param string|null $format the format param.
* @param string $expected the expected string.
*/
public function test_get_time_interval_string(int $time1, int $time2, ?string $format, string $expected) {
if (is_null($format)) {
$this->assertEquals($expected, get_time_interval_string($time1, $time2));
} else {
$this->assertEquals($expected, get_time_interval_string($time1, $time2, $format));
}
}
/**
* Data provider for the test_get_time_interval_string() method.
*/
public function get_time_interval_string_provider() {
return [
'Time is after the reference time by 1 minute, omitted format' => [
'time1' => 12345660,
'time2' => 12345600,
'format' => null,
'expected' => '0d 0h 1m'
],
'Time is before the reference time by 1 minute, omitted format' => [
'time1' => 12345540,
'time2' => 12345600,
'format' => null,
'expected' => '0d 0h 1m'
],
'Time is equal to the reference time, omitted format' => [
'time1' => 12345600,
'time2' => 12345600,
'format' => null,
'expected' => '0d 0h 0m'
],
'Time is after the reference time by 1 minute, empty string format' => [
'time1' => 12345660,
'time2' => 12345600,
'format' => '',
'expected' => '0d 0h 1m'
],
'Time is before the reference time by 1 minute, empty string format' => [
'time1' => 12345540,
'time2' => 12345600,
'format' => '',
'expected' => '0d 0h 1m'
],
'Time is equal to the reference time, empty string format' => [
'time1' => 12345600,
'time2' => 12345600,
'format' => '',
'expected' => '0d 0h 0m'
],
'Time is after the reference time by 1 minute, custom format' => [
'time1' => 12345660,
'time2' => 12345600,
'format' => '%R%adays %hhours %imins',
'expected' => '+0days 0hours 1mins'
],
'Time is before the reference time by 1 minute, custom format' => [
'time1' => 12345540,
'time2' => 12345600,
'format' => '%R%adays %hhours %imins',
'expected' => '-0days 0hours 1mins'
],
'Time is equal to the reference time, custom format' => [
'time1' => 12345600,
'time2' => 12345600,
'format' => '%R%adays %hhours %imins',
'expected' => '+0days 0hours 0mins'
],
];
}
}
+4 -4
View File
@@ -2821,10 +2821,10 @@ class mod_assign_external extends external_api {
'requiregrading' => $participant->requiregrading,
'grantedextension' => $participant->grantedextension,
'blindmarking' => $assign->is_blind_marking(),
'allowsubmissionsfromdate' => $assign->get_instance()->allowsubmissionsfromdate,
'duedate' => $assign->get_instance()->duedate,
'cutoffdate' => $assign->get_instance()->cutoffdate,
'duedatestr' => userdate($assign->get_instance()->duedate, get_string('strftimedatetime', 'langconfig')),
'allowsubmissionsfromdate' => $assign->get_instance($userid)->allowsubmissionsfromdate,
'duedate' => $assign->get_instance($userid)->duedate,
'cutoffdate' => $assign->get_instance($userid)->cutoffdate,
'duedatestr' => userdate($assign->get_instance($userid)->duedate, get_string('strftimedatetime', 'langconfig')),
);
if (!empty($participant->groupid)) {
+26 -2
View File
@@ -167,6 +167,22 @@ class assign_grading_table extends table_sql implements renderable {
ON u.id = uf.userid
AND uf.assignment = :assignmentid3 ';
if ($this->assignment->get_course()->relativedatesmode) {
$params['courseid1'] = $this->assignment->get_course()->id;
$from .= ' LEFT JOIN (
SELECT ue1.userid as enroluserid,
CASE WHEN MIN(ue1.timestart - c2.startdate) < 0 THEN 0 ELSE MIN(ue1.timestart - c2.startdate) END as enrolstartoffset
FROM {enrol} e1
JOIN {user_enrolments} ue1
ON (ue1.enrolid = e1.id AND ue1.status = 0)
JOIN {course} c2
ON c2.id = e1.courseid
WHERE e1.courseid = :courseid1 AND e1.status = 0
GROUP BY ue1.userid
) enroloffset
ON (enroloffset.enroluserid = u.id) ';
}
$hasoverrides = $this->assignment->has_overrides();
if ($hasoverrides) {
@@ -242,6 +258,14 @@ class assign_grading_table extends table_sql implements renderable {
)
) effective ON effective.priority = priority.priority AND effective.userid = priority.userid ';
} else if ($this->assignment->get_course()->relativedatesmode) {
// In relative dates mode and when we don't have overrides, include the
// duedate, cutoffdate and allowsubmissionsfrom date anyway as this information is useful and can vary.
$params['assignmentid5'] = (int)$this->assignment->get_instance()->id;
$fields .= ', a.duedate + enroloffset.enrolstartoffset as duedate, ';
$fields .= 'a.allowsubmissionsfromdate, ';
$fields .= 'a.cutoffdate ';
$from .= 'JOIN {assign} a ON a.id = :assignmentid5 ';
}
if (!empty($this->assignment->get_instance()->blindmarking)) {
@@ -377,7 +401,7 @@ class assign_grading_table extends table_sql implements renderable {
$columns[] = 'status';
$headers[] = get_string('status', 'assign');
if ($hasoverrides) {
if ($hasoverrides || $this->assignment->get_course()->relativedatesmode) {
// Allowsubmissionsfromdate.
$columns[] = 'allowsubmissionsfromdate';
$headers[] = get_string('allowsubmissionsfromdate', 'assign');
@@ -1034,7 +1058,7 @@ class assign_grading_table extends table_sql implements renderable {
public function col_status(stdClass $row) {
$o = '';
$instance = $this->assignment->get_instance();
$instance = $this->assignment->get_instance($row->userid);
$due = $instance->duedate;
if ($row->extensionduedate) {
+3
View File
@@ -430,6 +430,9 @@ $string['quickgrading'] = 'Quick grading';
$string['quickgradingresult'] = 'Quick grading';
$string['quickgradingchangessaved'] = 'The grade changes were saved';
$string['quickgrading_help'] = 'Quick grading allows you to assign grades (and outcomes) directly in the submissions table. Quick grading is not compatible with advanced grading and is not recommended when there are multiple markers.';
$string['relativedatessubmissiontimeleft'] = 'Calculated for each student';
$string['relativedatessubmissionduedateafter'] = '{$a->datediffstr} after course start';
$string['relativedatessubmissionduedatebefore'] = '{$a->datediffstr} before course start';
$string['removeallgroupoverrides'] = 'Delete all group overrides';
$string['removealluseroverrides'] = 'Delete all user overrides';
$string['reopenuntilpassincompatiblewithblindmarking'] = 'Reopen until pass option is incompatible with blind marking, because the grades are not released to the gradebook until the student identities are revealed.';
+91 -40
View File
@@ -104,6 +104,9 @@ class assign {
/** @var stdClass the assignment record that contains the global settings for this assign instance */
private $instance;
/** @var array $var array an array containing per-user assignment records, each having calculated properties (e.g. dates) */
private $userinstances = [];
/** @var grade_item the grade_item record for this assign instance's primary grade item. */
private $gradeitem;
@@ -1638,26 +1641,65 @@ class assign {
}
/**
* Get the settings for the current instance of this assignment
* Get the settings for the current instance of this assignment.
*
* @return stdClass The settings
* @throws dml_exception
*/
public function get_instance() {
public function get_default_instance() {
global $DB;
if ($this->instance) {
return $this->instance;
}
if ($this->get_course_module()) {
if (!$this->instance && $this->get_course_module()) {
$params = array('id' => $this->get_course_module()->instance);
$this->instance = $DB->get_record('assign', $params, '*', MUST_EXIST);
}
if (!$this->instance) {
throw new coding_exception('Improper use of the assignment class. ' .
'Cannot load the assignment record.');
$this->userinstances = [];
}
return $this->instance;
}
/**
* Get the settings for the current instance of this assignment
* @param int|null $userid the id of the user to load the assign instance for.
* @return stdClass The settings
*/
public function get_instance(int $userid = null) : stdClass {
global $USER;
$userid = $userid ?? $USER->id;
$this->instance = $this->get_default_instance();
// If we have the user instance already, just return it.
if (isset($this->userinstances[$userid])) {
return $this->userinstances[$userid];
}
// Calculate properties which vary per user.
$this->userinstances[$userid] = $this->calculate_properties($this->instance, $userid);
return $this->userinstances[$userid];
}
/**
* Calculates and updates various properties based on the specified user.
*
* @param stdClass $record the raw assign record.
* @param int $userid the id of the user to calculate the properties for.
* @return stdClass a new record having calculated properties.
*/
private function calculate_properties(\stdClass $record, int $userid) : \stdClass {
$record = clone ($record);
// Relative dates.
if (!empty($record->duedate)) {
$course = $this->get_course();
$usercoursedates = course_get_course_dates_for_user_id($course, $userid);
if ($usercoursedates['start']) {
$userprops = ['duedate' => $record->duedate + $usercoursedates['startoffset']];
$record = (object) array_merge((array) $record, (array) $userprops);
}
}
return $record;
}
/**
* Get the primary grade item for this assign instance.
*
@@ -1737,7 +1779,7 @@ class assign {
public function get_course() {
global $DB;
if ($this->course) {
if ($this->course && is_object($this->course)) {
return $this->course;
}
@@ -3864,10 +3906,9 @@ class assign {
* @return string
*/
protected function view_single_grading_panel($args) {
global $DB, $CFG, $SESSION, $PAGE;
global $DB, $CFG;
$o = '';
$instance = $this->get_instance();
require_once($CFG->dirroot . '/mod/assign/gradeform.php');
@@ -3877,6 +3918,7 @@ class assign {
// If userid is passed - we are only grading a single student.
$userid = $args['userid'];
$attemptnumber = $args['attemptnumber'];
$instance = $this->get_instance($userid);
// Apply overrides.
$this->update_effective_access($userid);
@@ -5520,8 +5562,9 @@ class assign {
*/
public function get_assign_grading_summary_renderable($activitygroup = null) {
$instance = $this->get_instance();
$instance = $this->get_default_instance(); // Grading summary requires the raw dates, regardless of relativedates mode.
$cm = $this->get_course_module();
$course = $this->get_course();
$draft = ASSIGN_SUBMISSION_STATUS_DRAFT;
$submitted = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
@@ -5542,35 +5585,43 @@ class assign {
}
}
$summary = new assign_grading_summary($this->count_teams($activitygroup),
$instance->submissiondrafts,
$this->count_submissions_with_status($draft, $activitygroup),
$this->is_any_submission_plugin_enabled(),
$this->count_submissions_with_status($submitted, $activitygroup),
$instance->cutoffdate,
$instance->duedate,
$this->get_course_module()->id,
$this->count_submissions_need_grading($activitygroup),
$instance->teamsubmission,
$warnofungroupedusers,
$this->can_grade(),
$isvisible);
$summary = new assign_grading_summary(
$this->count_teams($activitygroup),
$instance->submissiondrafts,
$this->count_submissions_with_status($draft, $activitygroup),
$this->is_any_submission_plugin_enabled(),
$this->count_submissions_with_status($submitted, $activitygroup),
$instance->cutoffdate,
$instance->duedate,
$this->get_course_module()->id,
$this->count_submissions_need_grading($activitygroup),
$instance->teamsubmission,
$warnofungroupedusers,
$course->relativedatesmode,
$course->startdate,
$this->can_grade(),
$isvisible
);
} else {
// The active group has already been updated in groups_print_activity_menu().
$countparticipants = $this->count_participants($activitygroup);
$summary = new assign_grading_summary($countparticipants,
$instance->submissiondrafts,
$this->count_submissions_with_status($draft, $activitygroup),
$this->is_any_submission_plugin_enabled(),
$this->count_submissions_with_status($submitted, $activitygroup),
$instance->cutoffdate,
$instance->duedate,
$this->get_course_module()->id,
$this->count_submissions_need_grading($activitygroup),
$instance->teamsubmission,
assign_grading_summary::WARN_GROUPS_NO,
$this->can_grade(),
$isvisible);
$summary = new assign_grading_summary(
$countparticipants,
$instance->submissiondrafts,
$this->count_submissions_with_status($draft, $activitygroup),
$this->is_any_submission_plugin_enabled(),
$this->count_submissions_with_status($submitted, $activitygroup),
$instance->cutoffdate,
$instance->duedate,
$this->get_course_module()->id,
$this->count_submissions_need_grading($activitygroup),
$instance->teamsubmission,
assign_grading_summary::WARN_GROUPS_NO,
$course->relativedatesmode,
$course->startdate,
$this->can_grade(),
$isvisible
);
}
return $summary;
+10
View File
@@ -748,6 +748,10 @@ class assign_grading_summary implements renderable {
public $teamsubmission = false;
/** @var boolean warnofungroupedusers - Do we need to warn people that there are users without groups */
public $warnofungroupedusers = false;
/** @var boolean relativedatesmode - Is the course a relative dates mode course or not */
public $courserelativedatesmode = false;
/** @var int coursestartdate - start date of the course as a unix timestamp*/
public $coursestartdate;
/** @var boolean cangrade - Can the current user grade students? */
public $cangrade = false;
/** @var boolean isvisible - Is the assignment's context module visible to students? */
@@ -774,6 +778,8 @@ class assign_grading_summary implements renderable {
* @param int $submissionsneedgradingcount
* @param bool $teamsubmission
* @param string $warnofungroupedusers
* @param bool $courserelativedatesmode true if the course is using relative dates, false otherwise.
* @param int $coursestartdate unix timestamp representation of the course start date.
* @param bool $cangrade
* @param bool $isvisible
*/
@@ -788,6 +794,8 @@ class assign_grading_summary implements renderable {
$submissionsneedgradingcount,
$teamsubmission,
$warnofungroupedusers,
$courserelativedatesmode,
$coursestartdate,
$cangrade = true,
$isvisible = true) {
$this->participantcount = $participantcount;
@@ -801,6 +809,8 @@ class assign_grading_summary implements renderable {
$this->submissionsneedgradingcount = $submissionsneedgradingcount;
$this->teamsubmission = $teamsubmission;
$this->warnofungroupedusers = $warnofungroupedusers;
$this->courserelativedatesmode = $courserelativedatesmode;
$this->coursestartdate = $coursestartdate;
$this->cangrade = $cangrade;
$this->isvisible = $isvisible;
}
+20 -5
View File
@@ -312,15 +312,30 @@ class mod_assign_renderer extends plugin_renderer_base {
if ($summary->duedate) {
// Due date.
$duedate = $summary->duedate;
if ($summary->courserelativedatesmode) {
// Returns a formatted string, in the format '10d 10h 45m'.
$diffstr = get_time_interval_string($duedate, $summary->coursestartdate);
if ($duedate >= $summary->coursestartdate) {
$userduedate = get_string('relativedatessubmissionduedateafter', 'mod_assign', ['datediffstr' => $diffstr]);
} else {
$userduedate = get_string('relativedatessubmissionduedatebefore', 'mod_assign', ['datediffstr' => $diffstr]);
}
} else {
$userduedate = userdate($duedate);
}
$this->add_table_row_tuple($t, get_string('duedate', 'assign'),
userdate($duedate));
$userduedate);
// Time remaining.
$due = '';
if ($duedate - $time <= 0) {
$due = get_string('assignmentisdue', 'assign');
if ($summary->courserelativedatesmode) {
$due = get_string('relativedatessubmissiontimeleft', 'mod_assign');
} else {
$due = format_time($duedate - $time);
$due = '';
if ($duedate - $time <= 0) {
$due = get_string('assignmentisdue', 'assign');
} else {
$due = format_time($duedate - $time);
}
}
$this->add_table_row_tuple($t, get_string('timeremaining', 'assign'), $due);
@@ -0,0 +1,67 @@
@mod @mod_assign
Feature: As a teacher in course with relative dates mode enabled
I should be able to create an assignment with a due date relative to the course start date
So that students can enter the course at any time and have a fixed period in which to submit the assignment
Scenario: As a student the due date for submitting my assignment is relative to my course start date
Given the following config values are set as admin:
| enablecourserelativedates | 1 |
And the following "courses" exist:
| fullname | shortname | category | groupmode | relativedatesmode | startdate |
| Course 1 | C1 | 0 | 1 | 1 | ##first day of -2 months## |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
| student2 | Student | 2 | student1@example.com |
And the following "course enrolments" exist:
# Two students, one started 2 months ago and one this month.
| user | course | role | timestart |
| teacher1 | C1 | editingteacher | ##first day of last month## |
| student1 | C1 | student | ##first day of -2 months## |
| student2 | C1 | student | ##first day of this month## |
And the following "activities" exist:
| activity | name | intro | course | idnumber | assignsubmission_onlinetext_enabled | timeopen | duedate |
| assign | Test assignment name | Test assignment description | C1 | assign0 | 1 |##first day of -2 months## | ##last day of -2 months## |
When I log in as "student1"
And I am on "Course 1" course homepage
And I follow "Test assignment name"
Then I should see "Assignment is overdue by:" in the "Time remaining" "table_row"
And I log out
And I log in as "student2"
And I am on "Course 1" course homepage
And I follow "Test assignment name"
And I should not see "Assignment is overdue by:" in the "Time remaining" "table_row"
And I log out
Scenario: As a teacher, I should see the relative dates when reviewing assignment submissions
Given the following config values are set as admin:
| enablecourserelativedates | 1 |
And the following "courses" exist:
| fullname | shortname | category | groupmode | relativedatesmode | startdate |
| Course 1 | C1 | 0 | 1 | 1 | ##first day of 3 months ago## |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
| student2 | Student | 2 | student1@example.com |
And the following "course enrolments" exist:
# Two students, one started 3 months ago and one this month.
| user | course | role | timestart |
| teacher1 | C1 | editingteacher | ##first day of 3 months ago## |
| student1 | C1 | student | ##first day of 3 months ago## |
| student2 | C1 | student | ##first day of this month## |
And the following "activities" exist:
| activity | name | intro | course | idnumber | assignsubmission_onlinetext_enabled | timeopen | duedate |
| assign | Test assignment name | Test assignment description | C1 | assign0 | 1 |##first day of 3 months ago## | ##first day of 2 months ago## |
And I log in as "teacher1"
And I am on "Course 1" course homepage
And I follow "Test assignment name"
And I should see "after course start" in the "Due date" "table_row"
And I should see "Calculated for each student" in the "Time remaining" "table_row"
When I navigate to "View all submissions" in current page administration
Then I should see "No submission" in the "Student 1" "table_row"
And I should see "Assignment is overdue by:" in the "Student 1" "table_row"
And I should see "No submission" in the "Student 2" "table_row"
And I should not see "Assignment is overdue by:" in the "Student 2" "table_row"
And I log out
+60
View File
@@ -2467,6 +2467,66 @@ class mod_assign_external_testcase extends externallib_advanced_testcase {
$this->assertEquals($group->name, $result['groupname']);
}
/**
* Test get_participant() when relative dates mode is enabled on the course.
*
* @dataProvider get_participant_relative_dates_provider
* @param array $courseconfig the config to use when creating the course.
* @param array $assignconfig the config to use when creating the assignment.
* @param array $enrolconfig the enrolement to create.
* @param array $expectedproperties array of expected assign properties.
*/
public function test_get_participant_relative_dates(array $courseconfig, array $assignconfig, array $enrolconfig,
array $expectedproperties) {
$this->resetAfterTest();
set_config('enablecourserelativedates', true); // Enable relative dates at site level.
$course = $this->getDataGenerator()->create_course($courseconfig);
$generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
$assignconfig['course'] = $course->id;
$instance = $generator->create_instance($assignconfig);
$cm = get_coursemodule_from_instance('assign', $instance->id);
$context = context_module::instance($cm->id);
$assign = new assign($context, $cm, $course);
$user = $this->getDataGenerator()->create_and_enrol($course, ...array_values($enrolconfig));
$teacher = $this->getDataGenerator()->create_and_enrol($course, 'teacher', null, 'manual', time() - 50 * DAYSECS);
$this->setUser($teacher);
$result = mod_assign_external::get_participant($assign->get_instance()->id, $user->id, false);
$result = external_api::clean_returnvalue(mod_assign_external::get_participant_returns(), $result);
foreach ($expectedproperties as $propertyname => $propertyval) {
$this->assertEquals($propertyval, $result[$propertyname]);
}
}
/**
* The test_get_participant_relative_dates data provider.
*/
public function get_participant_relative_dates_provider() {
$timenow = time();
return [
'Student whose enrolment starts after the course start date, relative dates mode enabled' => [
'courseconfig' => ['relativedatesmode' => true, 'startdate' => $timenow - 10 * DAYSECS],
'assignconfig' => ['duedate' => $timenow + 4 * DAYSECS],
'enrolconfig' => ['shortname' => 'student', 'userparams' => null, 'method' => 'manual',
'startdate' => $timenow - 8 * DAYSECS],
'expectedproperties' => ['duedate' => $timenow + 6 * DAYSECS]
],
'Student whose enrolment starts before the course start date, relative dates mode enabled' => [
'courseconfig' => ['relativedatesmode' => true, 'startdate' => $timenow - 10 * DAYSECS],
'assignconfig' => ['duedate' => $timenow + 4 * DAYSECS],
'enrolconfig' => ['shortname' => 'student', 'userparams' => null, 'method' => 'manual',
'startdate' => $timenow - 12 * DAYSECS],
'expectedproperties' => ['duedate' => $timenow + 4 * DAYSECS]
],
];
}
/**
* Test for mod_assign_external::list_participants().
*
+147
View File
@@ -4010,4 +4010,151 @@ Anchor link 2:<a title=\"bananas\" href=\"../logo-240x60.gif\">Link text</a>
$this->assertEquals(count($valid), 5);
}
/**
* Test assign->get_instance() for a number of cases, as defined in the data provider.
*
* @dataProvider assign_get_instance_provider
* @param array $courseconfig the config to use when creating the course.
* @param array $assignconfig the config to use when creating the assignment.
* @param array $enrolconfig the config to use when enrolling the user (this will be the active user).
* @param array $expectedproperties an map containing the expected names and values for the assign instance data.
*/
public function test_assign_get_instance(array $courseconfig, array $assignconfig, array $enrolconfig,
array $expectedproperties) {
$this->resetAfterTest();
set_config('enablecourserelativedates', true); // Enable relative dates at site level.
$course = $this->getDataGenerator()->create_course($courseconfig);
$assign = $this->create_instance($course, $assignconfig);
$user = $this->getDataGenerator()->create_and_enrol($course, ...array_values($enrolconfig));
$instance = $assign->get_instance($user->id);
foreach ($expectedproperties as $propertyname => $propertyval) {
$this->assertEquals($propertyval, $instance->$propertyname);
}
}
/**
* The test_assign_get_instance data provider.
*/
public function assign_get_instance_provider() {
$timenow = time();
// The get_default_instance() method shouldn't calculate any properties per-user. It should just return the record data.
// We'll confirm this works for a few different user types anyway, just like we do for get_instance().
return [
'Teacher whose enrolment starts after the course start date, relative dates mode enabled' => [
'courseconfig' => ['relativedatesmode' => true, 'startdate' => $timenow - 10 * DAYSECS],
'assignconfig' => ['duedate' => $timenow + 4 * DAYSECS],
'enrolconfig' => ['shortname' => 'teacher', 'userparams' => null, 'method' => 'manual',
'startdate' => $timenow - 8 * DAYSECS],
'expectedproperties' => ['duedate' => $timenow + 6 * DAYSECS]
],
'Teacher whose enrolment starts before the course start date, relative dates mode enabled' => [
'courseconfig' => ['relativedatesmode' => true, 'startdate' => $timenow - 10 * DAYSECS],
'assignconfig' => ['duedate' => $timenow + 4 * DAYSECS],
'enrolconfig' => ['shortname' => 'teacher', 'userparams' => null, 'method' => 'manual',
'startdate' => $timenow - 12 * DAYSECS],
'expectedproperties' => ['duedate' => $timenow + 4 * DAYSECS]
],
'Teacher whose enrolment starts after the course start date, relative dates mode disabled' => [
'courseconfig' => ['relativedatesmode' => false, 'startdate' => $timenow - 10 * DAYSECS],
'assignconfig' => ['duedate' => $timenow + 4 * DAYSECS],
'enrolconfig' => ['shortname' => 'teacher', 'userparams' => null, 'method' => 'manual',
'startdate' => $timenow - 8 * DAYSECS],
'expectedproperties' => ['duedate' => $timenow + 4 * DAYSECS]
],
'Student whose enrolment starts after the course start date, relative dates mode enabled' => [
'courseconfig' => ['relativedatesmode' => true, 'startdate' => $timenow - 10 * DAYSECS],
'assignconfig' => ['duedate' => $timenow + 4 * DAYSECS],
'enrolconfig' => ['shortname' => 'student', 'userparams' => null, 'method' => 'manual',
'startdate' => $timenow - 8 * DAYSECS],
'expectedproperties' => ['duedate' => $timenow + 6 * DAYSECS]
],
'Student whose enrolment starts before the course start date, relative dates mode enabled' => [
'courseconfig' => ['relativedatesmode' => true, 'startdate' => $timenow - 10 * DAYSECS],
'assignconfig' => ['duedate' => $timenow + 4 * DAYSECS],
'enrolconfig' => ['shortname' => 'student', 'userparams' => null, 'method' => 'manual',
'startdate' => $timenow - 12 * DAYSECS],
'expectedproperties' => ['duedate' => $timenow + 4 * DAYSECS]
],
'Student whose enrolment starts after the course start date, relative dates mode disabled' => [
'courseconfig' => ['relativedatesmode' => false, 'startdate' => $timenow - 10 * DAYSECS],
'assignconfig' => ['duedate' => $timenow + 4 * DAYSECS],
'enrolconfig' => ['shortname' => 'student', 'userparams' => null, 'method' => 'manual',
'startdate' => $timenow - 8 * DAYSECS],
'expectedproperties' => ['duedate' => $timenow + 4 * DAYSECS]
],
];
}
/**
* Test assign->get_default_instance() for a number of cases, as defined in the date provider.
*
* @dataProvider assign_get_default_instance_provider
* @param array $courseconfig the config to use when creating the course.
* @param array $assignconfig the config to use when creating the assignment.
* @param array $enrolconfig the config to use when enrolling the user (this will be the active user).
* @param array $expectedproperties an map containing the expected names and values for the assign instance data.
*/
public function test_assign_get_default_instance(array $courseconfig, array $assignconfig, array $enrolconfig,
array $expectedproperties) {
$this->resetAfterTest();
set_config('enablecourserelativedates', true); // Enable relative dates at site level.
$course = $this->getDataGenerator()->create_course($courseconfig);
$assign = $this->create_instance($course, $assignconfig);
$user = $this->getDataGenerator()->create_and_enrol($course, ...array_values($enrolconfig));
$this->setUser($user);
$defaultinstance = $assign->get_default_instance();
foreach ($expectedproperties as $propertyname => $propertyval) {
$this->assertEquals($propertyval, $defaultinstance->$propertyname);
}
}
/**
* The test_assign_get_default_instance data provider.
*/
public function assign_get_default_instance_provider() {
$timenow = time();
// The get_default_instance() method shouldn't calculate any properties per-user. It should just return the record data.
// We'll confirm this works for a few different user types anyway, just like we do for get_instance().
return [
'Teacher whose enrolment starts after the course start date, relative dates mode enabled' => [
'courseconfig' => ['relativedatesmode' => true, 'startdate' => $timenow - 10 * DAYSECS],
'assignconfig' => ['duedate' => $timenow + 4 * DAYSECS],
'enrolconfig' => ['shortname' => 'teacher', 'userparams' => null, 'method' => 'manual',
'startdate' => $timenow - 8 * DAYSECS],
'expectedproperties' => ['duedate' => $timenow + 4 * DAYSECS]
],
'Teacher whose enrolment starts before the course start date, relative dates mode enabled' => [
'courseconfig' => ['relativedatesmode' => true, 'startdate' => $timenow - 10 * DAYSECS],
'assignconfig' => ['duedate' => $timenow + 4 * DAYSECS],
'enrolconfig' => ['shortname' => 'teacher', 'userparams' => null, 'method' => 'manual',
'startdate' => $timenow - 12 * DAYSECS],
'expectedproperties' => ['duedate' => $timenow + 4 * DAYSECS]
],
'Teacher whose enrolment starts after the course start date, relative dates mode disabled' => [
'courseconfig' => ['relativedatesmode' => false, 'startdate' => $timenow - 10 * DAYSECS],
'assignconfig' => ['duedate' => $timenow + 4 * DAYSECS],
'enrolconfig' => ['shortname' => 'teacher', 'userparams' => null, 'method' => 'manual',
'startdate' => $timenow - 8 * DAYSECS],
'expectedproperties' => ['duedate' => $timenow + 4 * DAYSECS]
],
'Student whose enrolment starts after the course start date, relative dates mode enabled' => [
'courseconfig' => ['relativedatesmode' => true, 'startdate' => $timenow - 10 * DAYSECS],
'assignconfig' => ['duedate' => $timenow + 4 * DAYSECS],
'enrolconfig' => ['shortname' => 'student', 'userparams' => null, 'method' => 'manual',
'startdate' => $timenow - 8 * DAYSECS],
'expectedproperties' => ['duedate' => $timenow + 4 * DAYSECS]
],
];
}
}