MDL-57730 mod_assign: added action events

Part of MDL-55611 epic.
This commit is contained in:
Mark Nelson 2017-02-16 16:33:27 +08:00 committed by Damyon Wiese
parent bb19f80414
commit 294dce6764
3 changed files with 321 additions and 51 deletions

View File

@ -252,6 +252,7 @@ function assign_update_events($assign, $override = null) {
$addclose = empty($current->id) || !empty($current->duedate);
$event = new stdClass();
$event->type = CALENDAR_EVENT_TYPE_ACTION;
$event->description = format_module_intro('assign', $assigninstance, $cmid);
// Events module won't show user events when the courseid is nonzero.
$event->courseid = ($userid) ? 0 : $assigninstance->course;
@ -261,8 +262,9 @@ function assign_update_events($assign, $override = null) {
$event->instance = $assigninstance->id;
$event->timestart = $duedate;
$event->timeduration = 0;
$event->timesort = $event->timestart + $event->timeduration;
$event->visible = instance_is_visible('assign', $assigninstance);
$event->eventtype = 'due';
$event->eventtype = ASSIGN_EVENT_TYPE_OPEN;
// Determine the event name and priority.
if ($groupid) {
@ -299,7 +301,7 @@ function assign_update_events($assign, $override = null) {
}
$event->name = $eventname.' ('.get_string('duedate', 'assign').')';
$event->timestart = $duedate;
$event->eventtype = 'due';
$event->eventtype = ASSIGN_EVENT_TYPE_CLOSE;
\core_calendar\event::create($event);
}
}
@ -1707,15 +1709,68 @@ function assign_check_updates_since(cm_info $cm, $from, $filter = array()) {
return $updates;
}
//XXX: Rubbish implementation
function mod_assign_core_calendar_provide_event_action(
\core_calendar\event $event,
\core_calendar\action_factory $factory
) {
/**
* Is the event visible?
*
* @param \core_calendar\event $event
* @return bool Returns true if the event is visible to the current user, false otherwise.
*/
function mod_assign_core_calendar_is_event_visible(\core_calendar\event $event) {
global $USER;
$cm = get_fast_modinfo($event->courseid)->instances['assign'][$event->instance];
$context = context_module::instance($cm->id);
$assign = new assign($context, $cm, null);
if ($event->eventtype == ASSIGN_EVENT_TYPE_GRADINGDUE) {
return $assign->can_grade();
} else {
return !$assign->can_grade() && $assign->can_view_submission($USER->id);
}
}
/**
* Handles creating actions for events.
*
* @param \core_calendar\event $event
* @param \core_calendar\action_factory $factory
* @return \core_calendar\local\event\value_objects\action|\core_calendar\local\interfaces\action_interface|null
*/
function mod_assign_core_calendar_provide_event_action(\core_calendar\event $event,
\core_calendar\action_factory $factory) {
global $CFG, $USER;
require_once($CFG->dirroot . '/mod/assign/locallib.php');
$cm = get_fast_modinfo($event->courseid)->instances['assign'][$event->instance];
$context = context_module::instance($cm->id);
$assign = new assign($context, $cm, null);
if ($event->eventtype == ASSIGN_EVENT_TYPE_GRADINGDUE) {
$name = get_string('grade');
$url = new \moodle_url('/mod/assign/view.php', [
'id' => $cm->id,
'action' => 'grader'
]);
$itemcount = $assign->count_submissions_need_grading();
$actionable = $assign->can_grade() && (time() >= $assign->get_instance()->allowsubmissionsfromdate);
} else {
$name = get_string('addsubmission', 'assign');
$url = new \moodle_url('/mod/assign/view.php', [
'id' => $cm->id,
'action' => 'editsubmission'
]);
$itemcount = 1;
$actionable = $assign->is_any_submission_plugin_enabled() && $assign->can_edit_submission($USER->id);
}
return $factory->create_instance(
'chef',
new \moodle_url('http://example.com'),
3,
true
$name,
$url,
$itemcount,
$actionable
);
}

View File

@ -68,6 +68,12 @@ define("ASSIGN_MAX_EVENT_LENGTH", "432000");
// Name of file area for intro attachments.
define('ASSIGN_INTROATTACHMENT_FILEAREA', 'introattachment');
// Event types.
define('ASSIGN_EVENT_TYPE_DUE', 'due');
define('ASSIGN_EVENT_TYPE_GRADINGDUE', 'gradingdue');
define('ASSIGN_EVENT_TYPE_OPEN', 'open');
define('ASSIGN_EVENT_TYPE_CLOSE', 'close');
require_once($CFG->libdir . '/accesslib.php');
require_once($CFG->libdir . '/formslib.php');
require_once($CFG->dirroot . '/repository/lib.php');
@ -1159,12 +1165,43 @@ class assign {
// Special case for add_instance as the coursemodule has not been set yet.
$instance = $this->get_instance();
$eventtype = 'due';
// Start with creating the event.
$event = new stdClass();
$event->modulename = 'assign';
$event->courseid = $instance->course;
$event->groupid = 0;
$event->userid = 0;
$event->instance = $instance->id;
$event->name = $instance->name;
$event->type = CALENDAR_EVENT_TYPE_ACTION;
// Convert the links to pluginfile. It is a bit hacky but at this stage the files
// might not have been saved in the module area yet.
$intro = $instance->intro;
if ($draftid = file_get_submitted_draft_itemid('introeditor')) {
$intro = file_rewrite_urls_to_pluginfile($intro, $draftid);
}
// We need to remove the links to files as the calendar is not ready
// to support module events with file areas.
$intro = strip_pluginfile_content($intro);
if ($this->show_intro()) {
$event->description = array(
'text' => $intro,
'format' => $instance->introformat
);
} else {
$event->description = array(
'text' => '',
'format' => $instance->introformat
);
}
$eventtype = ASSIGN_EVENT_TYPE_DUE;
if ($instance->duedate) {
$event = new stdClass();
// Fetch the original due date event. It will have a non-zero course ID and a zero group ID.
$event->eventtype = $eventtype;
$event->timestart = $instance->duedate;
$event->timesort = $instance->duedate;
$select = "modulename = :modulename
AND instance = :instance
AND eventtype = :eventtype
@ -1172,50 +1209,41 @@ class assign {
AND courseid <> 0";
$params = array('modulename' => 'assign', 'instance' => $instance->id, 'eventtype' => $eventtype);
$event->id = $DB->get_field_select('event', 'id', $select, $params);
$event->name = $instance->name;
$event->timestart = $instance->duedate;
// Convert the links to pluginfile. It is a bit hacky but at this stage the files
// might not have been saved in the module area yet.
$intro = $instance->intro;
if ($draftid = file_get_submitted_draft_itemid('introeditor')) {
$intro = file_rewrite_urls_to_pluginfile($intro, $draftid);
}
// We need to remove the links to files as the calendar is not ready
// to support module events with file areas.
$intro = strip_pluginfile_content($intro);
if ($this->show_intro()) {
$event->description = array(
'text' => $intro,
'format' => $instance->introformat
);
} else {
$event->description = array(
'text' => '',
'format' => $instance->introformat
);
}
// Now process the event.
if ($event->id) {
$calendarevent = \core_calendar\event::load($event->id);
$calendarevent->update($event);
} else {
unset($event->id);
$event->courseid = $instance->course;
$event->groupid = 0;
$event->userid = 0;
$event->modulename = 'assign';
$event->instance = $instance->id;
$event->eventtype = $eventtype;
$event->timeduration = 0;
\core_calendar\event::create($event);
}
} else {
$DB->delete_records('event', array('modulename' => 'assign', 'instance' => $instance->id, 'eventtype' => $eventtype));
$DB->delete_records('event', array('modulename' => 'assign', 'instance' => $instance->id,
'eventtype' => $eventtype));
}
}
$eventtype = ASSIGN_EVENT_TYPE_GRADINGDUE;
if ($instance->gradingduedate) {
$event->eventtype = $eventtype;
$event->timestart = $instance->gradingduedate;
$event->timesort = $instance->gradingduedate;
$event->id = $DB->get_field('event', 'id', array('modulename' => 'assign',
'instance' => $instance->id, 'eventtype' => $event->eventtype));
// Now process the event.
if ($event->id) {
$calendarevent = \core_calendar\event::load($event->id);
$calendarevent->update($event);
} else {
\core_calendar\event::create($event);
}
} else {
$DB->delete_records('event', array('modulename' => 'assign', 'instance' => $instance->id,
'eventtype' => $eventtype));
}
return true;
}
/**
* Update this instance in the database.
@ -3076,7 +3104,7 @@ class assign {
* Throw an error if the permissions to view this users submission are missing.
*
* @throws required_capability_exception
* @return void
* @return none
*/
public function require_view_submission($userid) {
if (!$this->can_view_submission($userid)) {
@ -3088,7 +3116,7 @@ class assign {
* Throw an error if the permissions to view grades in this assignment are missing.
*
* @throws required_capability_exception
* @return void
* @return none
*/
public function require_view_grades() {
if (!$this->can_view_grades()) {

View File

@ -380,4 +380,191 @@ class mod_assign_lib_testcase extends mod_assign_base_testcase {
$this->assertFalse(assign_refresh_events('aaa'));
}
public function test_assign_core_calendar_is_event_visible_duedate_event_as_teacher() {
$this->setAdminUser();
// Create an assignment.
$assign = $this->create_instance();
// Create a calendar event.
$event = $this->create_action_event($assign->get_instance()->id, ASSIGN_EVENT_TYPE_DUE);
// Set the user to a teacher.
$this->setUser($this->editingteachers[0]);
// The teacher should not care about the due date event.
$this->assertFalse(mod_assign_core_calendar_is_event_visible($event));
}
public function test_assign_core_calendar_is_event_visible_duedate_event_as_student() {
$this->setAdminUser();
// Create an assignment.
$assign = $this->create_instance(array('assignsubmission_onlinetext_enabled' => 1));
// Create a calendar event.
$event = $this->create_action_event($assign->get_instance()->id, ASSIGN_EVENT_TYPE_DUE);
// Set the user to a student.
$this->setUser($this->students[0]);
// The student should care about the due date event.
$this->assertTrue(mod_assign_core_calendar_is_event_visible($event));
}
public function test_assign_core_calendar_is_event_visible_gradingduedate_event_as_teacher() {
$this->setAdminUser();
// Create an assignment.
$assign = $this->create_instance();
// Create a calendar event.
$event = $this->create_action_event($assign->get_instance()->id, ASSIGN_EVENT_TYPE_GRADINGDUE);
// Set the user to a teacher.
$this->setUser($this->editingteachers[0]);
// The teacher should care about the grading due date event.
$this->assertTrue(mod_assign_core_calendar_is_event_visible($event));
}
public function test_assign_core_calendar_is_event_visible_gradingduedate_event_as_student() {
$this->setAdminUser();
// Create an assignment.
$assign = $this->create_instance();
// Create a calendar event.
$event = $this->create_action_event($assign->get_instance()->id, ASSIGN_EVENT_TYPE_GRADINGDUE);
// Set the user to a student.
$this->setUser($this->students[0]);
// The student should not care about the grading due date event.
$this->assertFalse(mod_assign_core_calendar_is_event_visible($event));
}
public function test_assign_core_calendar_provide_event_action_duedate_as_teacher() {
$this->setAdminUser();
// Create an assignment.
$assign = $this->create_instance(array('assignsubmission_onlinetext_enabled' => 1));
// Create a calendar event.
$event = $this->create_action_event($assign->get_instance()->id, ASSIGN_EVENT_TYPE_DUE);
// Create an action factory.
$factory = new \core_calendar\action_factory();
// Set the user to a teacher.
$this->setUser($this->teachers[0]);
// Decorate action event.
$actionevent = mod_assign_core_calendar_provide_event_action($event, $factory);
// Confirm the event was decorated.
$this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent);
$this->assertEquals(get_string('addsubmission', 'assign'), $actionevent->get_name());
$this->assertInstanceOf('moodle_url', $actionevent->get_url());
$this->assertEquals(1, $actionevent->get_item_count());
$this->assertFalse($actionevent->is_actionable());
}
public function test_assign_core_calendar_provide_event_action_duedate_as_student() {
$this->setAdminUser();
// Create an assignment.
$assign = $this->create_instance(array('assignsubmission_onlinetext_enabled' => 1));
// Create a calendar event.
$event = $this->create_action_event($assign->get_instance()->id, ASSIGN_EVENT_TYPE_DUE);
// Create an action factory.
$factory = new \core_calendar\action_factory();
// Set the user to a student.
$this->setUser($this->students[0]);
// Decorate action event.
$actionevent = mod_assign_core_calendar_provide_event_action($event, $factory);
// Confirm the event was decorated.
$this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent);
$this->assertEquals(get_string('addsubmission', 'assign'), $actionevent->get_name());
$this->assertInstanceOf('moodle_url', $actionevent->get_url());
$this->assertEquals(1, $actionevent->get_item_count());
$this->assertTrue($actionevent->is_actionable());
}
public function test_assign_core_calendar_provide_event_action_gradingduedate_as_teacher() {
$this->setAdminUser();
// Create an assignment.
$assign = $this->create_instance();
// Create a calendar event.
$event = $this->create_action_event($assign->get_instance()->id, ASSIGN_EVENT_TYPE_GRADINGDUE);
// Create an action factory.
$factory = new \core_calendar\action_factory();
// Set the user to a teacher.
$this->setUser($this->editingteachers[0]);
// Decorate action event.
$actionevent = mod_assign_core_calendar_provide_event_action($event, $factory);
// Confirm the event was decorated.
$this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent);
$this->assertEquals(get_string('grade'), $actionevent->get_name());
$this->assertInstanceOf('moodle_url', $actionevent->get_url());
$this->assertEquals(0, $actionevent->get_item_count());
$this->assertTrue($actionevent->is_actionable());
}
public function test_assign_core_calendar_provide_event_action_gradingduedate_as_student() {
$this->setAdminUser();
// Create an assignment.
$assign = $this->create_instance();
// Create a calendar event.
$event = $this->create_action_event($assign->get_instance()->id, ASSIGN_EVENT_TYPE_GRADINGDUE);
// Create an action factory.
$factory = new \core_calendar\action_factory();
// Set the user to a student.
$this->setUser($this->students[0]);
// Decorate action event.
$actionevent = mod_assign_core_calendar_provide_event_action($event, $factory);
// Confirm the event was decorated.
$this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent);
$this->assertEquals(get_string('grade'), $actionevent->get_name());
$this->assertInstanceOf('moodle_url', $actionevent->get_url());
$this->assertEquals(0, $actionevent->get_item_count());
$this->assertFalse($actionevent->is_actionable());
}
/**
* Creates an action event.
*
* @param int $instanceid The assign id.
* @param string $eventtype The event type. eg. ASSIGN_EVENT_TYPE_DUE.
* @return bool|\core_calendar\event
*/
private function create_action_event($instanceid, $eventtype) {
$event = new stdClass();
$event->name = 'Calendar event';
$event->modulename = 'assign';
$event->courseid = $this->course->id;
$event->instance = $instanceid;
$event->type = CALENDAR_EVENT_TYPE_ACTION;
$event->eventtype = $eventtype;
$event->timestart = time();
return \core_calendar\event::create($event);
}
}