MDL-31936 workshop: Add more options to the course reset form

This is built upon original work by Michael Hughes. We now have separate
settings for deleting workshop submissions, assessments and for resetting the
workshop phase.
This commit is contained in:
David Mudrák 2014-09-17 21:36:13 +02:00
parent 4a44c660e5
commit f2639dca1d
3 changed files with 170 additions and 87 deletions

View File

@ -224,6 +224,12 @@ $string['reassess'] = 'Re-assess';
$string['receivedgrades'] = 'Grades received';
$string['recentassessments'] = 'Workshop assessments:';
$string['recentsubmissions'] = 'Workshop submissions:';
$string['resetassessments'] = 'Delete all assessments';
$string['resetassessments_help'] = 'You can choose to delete just allocated assessments without affecting submissions. If submissions are to be deleted, their assessments will be deleted implicitly and this option is ignored. Note this also includes assessments of example submissions.';
$string['resetsubmissions'] = 'Delete all submissions';
$string['resetsubmissions_help'] = 'All the submissions and their assessments will be deleted. This does not affect example submissions.';
$string['resetphase'] = 'Switch to the setup phase';
$string['resetphase_help'] = 'If enabled, all workshops will be put into the initial setup phase.';
$string['saveandclose'] = 'Save and close';
$string['saveandcontinue'] = 'Save and continue editing';
$string['saveandpreview'] = 'Save and preview';
@ -319,7 +325,6 @@ $string['workshop:viewauthornames'] = 'View author names';
$string['workshop:viewauthorpublished'] = 'View authors of published submissions';
$string['workshop:viewpublishedsubmissions'] = 'View published submissions';
$string['workshop:viewreviewernames'] = 'View reviewer names';
$string['resetworkshopall'] = 'Reset all';
$string['yourassessment'] = 'Your assessment';
$string['yourgrades'] = 'Your grades';
$string['yoursubmission'] = 'Your submission';

View File

@ -1696,39 +1696,79 @@ function workshop_calendar_update(stdClass $workshop, $cmid) {
}
}
/** Started MDL-31936 Reset work*/
function workshop_reset_course_form_definition(&$mform) {
$mform->addElement('header', 'workshopheader', get_string('modulenameplural', 'workshop'));
$mform->addElement('checkbox', 'reset_workshop_all', get_string('resetworkshopall', 'workshop'));
// ... @todo selective reset.
////////////////////////////////////////////////////////////////////////////////
// Course reset API //
////////////////////////////////////////////////////////////////////////////////
/**
* Extends the course reset form with workshop specific settings.
*
* @param MoodleQuickForm $mform
*/
function workshop_reset_course_form_definition($mform) {
$mform->addElement('header', 'workshopheader', get_string('modulenameplural', 'mod_workshop'));
$mform->addElement('advcheckbox', 'reset_workshop_submissions', get_string('resetsubmissions', 'mod_workshop'));
$mform->addHelpButton('reset_workshop_submissions', 'resetsubmissions', 'mod_workshop');
$mform->addElement('advcheckbox', 'reset_workshop_assessments', get_string('resetassessments', 'mod_workshop'));
$mform->addHelpButton('reset_workshop_assessments', 'resetassessments', 'mod_workshop');
$mform->disabledIf('reset_workshop_assessments', 'reset_workshop_submissions', 'checked');
$mform->addElement('advcheckbox', 'reset_workshop_phase', get_string('resetphase', 'mod_workshop'));
$mform->addHelpButton('reset_workshop_phase', 'resetphase', 'mod_workshop');
}
function workshop_reset_course_form_defaults($course) {
return array(
'reset_workshop_all' => 1
);
/**
* Provides default values for the workshop settings in the course reset form.
*
* @param stdClass $course The course to be reset.
*/
function workshop_reset_course_form_defaults(stdClass $course) {
$defaults = array(
'reset_workshop_submissions' => 1,
'reset_workshop_assessments' => 1,
'reset_workshop_phase' => 1,
);
return $defaults;
}
function workshop_reset_userdata($data) {
/**
* Performs the reset of all workshop instances in the course.
*
* @param stdClass $data The actual course reset settings.
* @return array List of results, each being array[(string)component, (string)item, (string)error]
*/
function workshop_reset_userdata(stdClass $data) {
global $CFG, $DB;
// Only if we have workshop modules.
if (!$workshops = $DB->get_records('workshop', array('course' => $data->courseid))) {
return false;
if (empty($data->reset_workshop_submissions)
and empty($data->reset_workshop_assessments)
and empty($data->reset_workshop_phase) ) {
// Nothing to do here.
return array();
}
require_once($CFG->dirroot . '/mod/workshop/locallib.php');
$course = $DB->get_record('course', array('id' => $data->courseid));
$componentstr = get_string('modulenameplural', 'workshop');
$workshoprecords = $DB->get_records('workshop', array('course' => $data->courseid));
if (empty($workshoprecords)) {
// What a boring course - no workshops here!
return array();
}
require_once($CFG->dirroot . '/mod/workshop/locallib.php');
$course = $DB->get_record('course', array('id' => $data->courseid), '*', MUST_EXIST);
$status = array();
foreach ($workshops as $workshop) {
$cm = get_coursemodule_from_instance("workshop", $workshop->id, $data->courseid);
$wx = new workshop($workshop, $cm, $course);
$status = array_merge($status, $wx->reset_userdata($data));
foreach ($workshoprecords as $workshoprecord) {
$cm = get_coursemodule_from_instance('workshop', $workshoprecord->id, $course->id, false, MUST_EXIST);
$workshop = new workshop($workshoprecord, $cm, $course);
$status = array_merge($status, $workshop->reset_userdata($data));
}
return $status;
}

View File

@ -1057,6 +1057,7 @@ class workshop {
*/
public function delete_submission(stdclass $submission) {
global $DB;
$assessments = $DB->get_records('workshop_assessments', array('submissionid' => $submission->id), '', 'id');
$this->delete_assessment(array_keys($assessments));
@ -2388,6 +2389,69 @@ class workshop {
);
}
/**
* Performs the reset of this workshop instance.
*
* @param stdClass $data The actual course reset settings.
* @return array List of results, each being array[(string)component, (string)item, (string)error]
*/
public function reset_userdata(stdClass $data) {
$componentstr = get_string('pluginname', 'workshop').': '.format_string($this->name);
$status = array();
if (!empty($data->reset_workshop_assessments) or !empty($data->reset_workshop_submissions)) {
// Reset all data related to assessments, including assessments of
// example submissions.
$result = $this->reset_userdata_assessments($data);
if ($result === true) {
$status[] = array(
'component' => $componentstr,
'item' => get_string('resetassessments', 'mod_workshop'),
'error' => false,
);
} else {
$status[] = array(
'component' => $componentstr,
'item' => get_string('resetassessments', 'mod_workshop'),
'error' => $result,
);
}
}
if (!empty($data->reset_workshop_submissions)) {
// Reset all remaining data related to submissions.
$result = $this->reset_userdata_submissions($data);
if ($result === true) {
$status[] = array(
'component' => $componentstr,
'item' => get_string('resetsubmissions', 'mod_workshop'),
'error' => false,
);
} else {
$status[] = array(
'component' => $componentstr,
'item' => get_string('resetsubmissions', 'mod_workshop'),
'error' => $result,
);
}
}
if (!empty($data->reset_workshop_phase)) {
// Do not use the {@link workshop::switch_phase()} here, we do not
// want to trigger events.
$this->reset_phase();
$status[] = array(
'component' => $componentstr,
'item' => get_string('resetsubmissions', 'mod_workshop'),
'error' => false,
);
}
return $status;
}
////////////////////////////////////////////////////////////////////////////////
// Internal methods (implementation details) //
////////////////////////////////////////////////////////////////////////////////
@ -2658,84 +2722,58 @@ class workshop {
return substr($fullurl->out(), strlen($baseurl));
}
/**
* Resets this activity's content
* @param array The reset data object.
* @return bool True if the reset was successful, false if there was an error
* Removes all user data related to assessments (including allocations).
*
* This includes assessments of example submissions as long as they are not
* referential assessments.
*
* @param stdClass $data The actual course reset settings.
* @return bool|string True on success, error message otherwise.
*/
public function reset_userdata($data) {
$componentstr = get_string('modulenameplural', 'workshop');
$status = array();
$this->reset_submissions();
$delaggregations = $DB->delete_records('workshop_aggregations', array('workshopid' => $this->id));
$this->reset_allocators();
$this->reset_evaluators();
$this->reset_strategies();
protected function reset_userdata_assessments(stdClass $data) {
global $DB;
$events = $DB->get_records('event', array('modulename' => 'workshop', 'instance' => $this->id));
foreach ($events as $event) {
$event = calendar_event::load($event);
$event->delete();
}
$sql = "SELECT a.id
FROM {workshop_assessments} a
JOIN {workshop_submissions} s ON (a.submissionid = s.id)
WHERE s.workshopid = :workshopid
AND (s.example = 0 OR (s.example = 1 AND a.weight = 0))";
// Set the phase.
// $DB->set_field('workshop', 'phase', 0, array('id' => $workshop->id)); // Left in to give option to switch back after discussion.
$this->switch_phase(self::PHASE_SETUP); // Use the API but we may not want to raise events about this....
$assessments = $DB->get_records_sql($sql, array('workshopid' => $this->id));
$this->delete_assessment(array_keys($assessments));
$status[] = array('component' => $componentstr, 'item' => get_string('resetworkshopall', 'workshop'), 'error' => false);
return $status;
$DB->delete_records('workshop_aggregations', array('workshopid' => $this->id));
return true;
}
/**
* Remove user content, including grades
* Removes all user data related to participants' submissions.
*
* @param stdClass $data The actual course reset settings.
* @return bool|string True on success, error message otherwise.
*/
protected function reset_submissions() {
$submissions = $this->get_submissions();
foreach ($submissions as $submission) {
$this->delete_submission($submission);
}
// Clean up submission files.
$fs = get_file_storage();
$files = $fs->get_area_files($this->context, 'mod_workshop', 'submission_attachment', false);
$numberfilestodelete = count($files);
$numfilesdeleted = 0;
foreach ($files as $file) {
try {
$file->delete();
$numfilesdeleted += 1;
}
catch (Exception $exception) {
// The delete can fail if necessary it just leaves an orphan in the DB. The record its attached to will have rady been removed.
}
}
}
protected function reset_allocators() {
$allocators = core_component::get_plugin_list('workshopallocation');
foreach ($allocators as $allocator => $path) {
require_once($path.'/lib.php');
$classname = 'workshop_'.$allocator.'_allocator';
call_user_func($classname.'::reset_user_data', $this->id);
protected function reset_userdata_submissions(stdClass $data) {
global $DB;
$submissions = $this->get_submissions();
foreach ($submissions as $submission) {
$this->delete_submission($submission);
}
return true;
}
protected function reset_strategies() {
$evaluators = core_component::get_plugin_list('workshopeval');
foreach ($evaluators as $evaluator => $path) {
require_once($path.'/lib.php');
$classname = 'workshop_'.$evaluator.'_evaluation';
call_user_func($classname.'::reset_user_data', $this->id);
}
}
/**
* Hard set the workshop phase to the setup one.
*/
protected function reset_phase() {
global $DB;
protected function reset_evaluators() {
$evaluators = core_component::get_plugin_list('workshopeval');
foreach ($evaluators as $evaluator => $path) {
require_once($path.'/lib.php');
$classname = 'workshop_'.$evaluator.'_evaluation';
call_user_func($classname.'::reset_user_data', $this->id);
}
$DB->set_field('workshop', 'phase', self::PHASE_SETUP, array('id' => $this->id));
$this->phase = self::PHASE_SETUP;
}
}