diff --git a/mod/workshop/backup/moodle1/lib.php b/mod/workshop/backup/moodle1/lib.php index 8dc55ecb2d4..4405280c6e3 100644 --- a/mod/workshop/backup/moodle1/lib.php +++ b/mod/workshop/backup/moodle1/lib.php @@ -105,6 +105,8 @@ class moodle1_mod_workshop_handler extends moodle1_mod_handler { $this->currentworkshop['instructreviewers'] = ''; $this->currentworkshop['instructreviewersformat'] = FORMAT_HTML; $this->currentworkshop['latesubmissions'] = 0; + $this->currentworkshop['conclusion'] = ''; + $this->currentworkshop['conclusionformat'] = FORMAT_HTML; foreach (array('submissionend', 'submissionstart', 'assessmentend', 'assessmentstart') as $field) { if (!array_key_exists($field, $this->currentworkshop)) { diff --git a/mod/workshop/backup/moodle2/backup_workshop_stepslib.php b/mod/workshop/backup/moodle2/backup_workshop_stepslib.php index 26e6adf84cc..7f194fb6bcf 100644 --- a/mod/workshop/backup/moodle2/backup_workshop_stepslib.php +++ b/mod/workshop/backup/moodle2/backup_workshop_stepslib.php @@ -55,7 +55,8 @@ class backup_workshop_activity_structure_step extends backup_activity_structure_ 'usepeerassessment', 'useselfassessment', 'grade', 'gradinggrade', 'strategy', 'evaluation', 'gradedecimals', 'nattachments', 'latesubmissions', 'maxbytes', 'examplesmode', 'submissionstart', - 'submissionend', 'assessmentstart', 'assessmentend')); + 'submissionend', 'assessmentstart', 'assessmentend', + 'conclusion', 'conclusionformat')); // assessment forms definition $this->add_subplugin_structure('workshopform', $workshop, true); @@ -194,6 +195,7 @@ class backup_workshop_activity_structure_step extends backup_activity_structure_ $workshop->annotate_files('mod_workshop', 'intro', null); // no itemid used $workshop->annotate_files('mod_workshop', 'instructauthors', null); // no itemid used $workshop->annotate_files('mod_workshop', 'instructreviewers', null); // no itemid used + $workshop->annotate_files('mod_workshop', 'conclusion', null); // no itemid used $examplesubmission->annotate_files('mod_workshop', 'submission_content', 'id'); $examplesubmission->annotate_files('mod_workshop', 'submission_attachment', 'id'); diff --git a/mod/workshop/backup/moodle2/restore_workshop_activity_task.class.php b/mod/workshop/backup/moodle2/restore_workshop_activity_task.class.php index 1f942f76569..eadb6a909bf 100644 --- a/mod/workshop/backup/moodle2/restore_workshop_activity_task.class.php +++ b/mod/workshop/backup/moodle2/restore_workshop_activity_task.class.php @@ -55,7 +55,7 @@ class restore_workshop_activity_task extends restore_activity_task { $contents = array(); $contents[] = new restore_decode_content('workshop', - array('intro', 'instructauthors', 'instructreviewers'), 'workshop'); + array('intro', 'instructauthors', 'instructreviewers', 'conclusion'), 'workshop'); $contents[] = new restore_decode_content('workshop_submissions', array('content', 'feedbackauthor'), 'workshop_submission'); $contents[] = new restore_decode_content('workshop_assessments', diff --git a/mod/workshop/backup/moodle2/restore_workshop_stepslib.php b/mod/workshop/backup/moodle2/restore_workshop_stepslib.php index dae77061b73..616bed8162e 100644 --- a/mod/workshop/backup/moodle2/restore_workshop_stepslib.php +++ b/mod/workshop/backup/moodle2/restore_workshop_stepslib.php @@ -212,6 +212,7 @@ class restore_workshop_activity_structure_step extends restore_activity_structur $this->add_related_files('mod_workshop', 'intro', null); $this->add_related_files('mod_workshop', 'instructauthors', null); $this->add_related_files('mod_workshop', 'instructreviewers', null); + $this->add_related_files('mod_workshop', 'conclusion', null); // Add example submission related files, matching by 'workshop_examplesubmission' itemname $this->add_related_files('mod_workshop', 'submission_content', 'workshop_examplesubmission'); diff --git a/mod/workshop/db/install.xml b/mod/workshop/db/install.xml index 6a323986064..1a9917634c4 100644 --- a/mod/workshop/db/install.xml +++ b/mod/workshop/db/install.xml @@ -1,5 +1,5 @@ - @@ -33,7 +33,9 @@ - + + + diff --git a/mod/workshop/db/upgrade.php b/mod/workshop/db/upgrade.php index 061d599c5be..d1446a37143 100644 --- a/mod/workshop/db/upgrade.php +++ b/mod/workshop/db/upgrade.php @@ -88,7 +88,25 @@ function xmldb_workshop_upgrade($oldversion) { } // Moodle v2.3.0 release upgrade line - // Put any upgrade step following this + + /** + * Add new fields conclusion and conclusionformat + */ + if ($oldversion < 2012102400) { + $table = new xmldb_table('workshop'); + + $field = new xmldb_field('conclusion', XMLDB_TYPE_TEXT, null, null, null, null, null, 'phaseswitchassessment'); + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + $field = new xmldb_field('conclusionformat', XMLDB_TYPE_INTEGER, '3', null, XMLDB_NOTNULL, null, '1', 'conclusion'); + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + upgrade_mod_savepoint(true, 2012102400, 'workshop'); + } return true; diff --git a/mod/workshop/lang/en/workshop.php b/mod/workshop/lang/en/workshop.php index f2fbd0dead1..c43c2e2c21f 100644 --- a/mod/workshop/lang/en/workshop.php +++ b/mod/workshop/lang/en/workshop.php @@ -35,6 +35,7 @@ $string['allocationerror'] = 'Allocation error'; $string['allocationconfigured'] = 'Allocation configured'; $string['allsubmissions'] = 'All submissions ({$a})'; $string['alreadygraded'] = 'Already graded'; +$string['areaconclusion'] = 'Conclusion text'; $string['areainstructauthors'] = 'Instructions for submission'; $string['areainstructreviewers'] = 'Instructions for assessment'; $string['areasubmissionattachment'] = 'Submission attachments'; @@ -77,6 +78,8 @@ $string['clearassessments'] = 'Clear assessments'; $string['clearassessments_help'] = 'The calculated grades for submission and grades for assessment will be reset. The information how the assessment forms are filled is still kept, but all the reviewers must open the assessment form again and re-save it to get the given grades calculated again.'; $string['clearassessmentsconfirm'] = 'Are you sure you want to clear all assessment grades? You will not be able to get the information back on your own, reviewers will have to re-assess the allocated submissions.'; $string['clearaggregatedgradesconfirm'] = 'Are you sure you want to clear the calculated grades for submissions and grades for assessment?'; +$string['conclusion'] = 'Conclusion'; +$string['conclusion_help'] = 'Conclusion is a text displayed to participants at the end of the activity. You may want to provide an overall feedback, summary or suggestions on what should be done next (e.g. writing a blog post reflecting the new experience).'; $string['configexamplesmode'] = 'Default mode of examples assessment in workshops'; $string['configgrade'] = 'Default maximum grade for submission in workshops'; $string['configgradedecimals'] = 'Default number of digits that should be shown after the decimal point when displaying grades.'; @@ -157,6 +160,7 @@ $string['latesubmissions_desc'] = 'Allow submissions after the deadline'; $string['latesubmissions_help'] = 'If enabled, an author may submit their work after the submissions deadline or during the assessment phase. Late submissions cannot be edited though.'; $string['latesubmissionsallowed'] = 'Late submissions are allowed'; $string['maxbytes'] = 'Maximum file size'; +$string['miscellaneoussettings'] = 'Miscellaneous settings'; $string['modulename'] = 'Workshop'; $string['modulename_help'] = 'The workshop activity module enables the collection, review and peer assessment of students\' work. @@ -255,6 +259,7 @@ $string['switchphase50info'] = 'You are about to close the workshop. This will r $string['taskassesspeers'] = 'Assess peers'; $string['taskassesspeersdetails'] = 'total: {$a->total}
pending: {$a->todo}'; $string['taskassessself'] = 'Assess yourself'; +$string['taskconclusion'] = 'Provide a conclusion of the activity'; $string['taskinstructauthors'] = 'Provide instructions for submission'; $string['taskinstructreviewers'] = 'Provide instructions for assessment'; $string['taskintro'] = 'Set the workshop introduction'; diff --git a/mod/workshop/lib.php b/mod/workshop/lib.php index 7250fe36676..b9d93c6fcfe 100644 --- a/mod/workshop/lib.php +++ b/mod/workshop/lib.php @@ -104,6 +104,12 @@ function workshop_add_instance(stdclass $workshop) { $workshop->instructreviewersformat = $workshop->instructreviewerseditor['format']; } + if ($draftitemid = $workshop->conclusioneditor['itemid']) { + $workshop->conclusion = file_save_draft_area_files($draftitemid, $context->id, 'mod_workshop', 'conclusion', + 0, workshop::instruction_editors_options($context), $workshop->conclusioneditor['text']); + $workshop->conclusionformat = $workshop->conclusioneditor['format']; + } + // re-save the record with the replaced URLs in editor fields $DB->update_record('workshop', $workshop); @@ -137,8 +143,7 @@ function workshop_update_instance(stdclass $workshop) { $workshop->latesubmissions = (int)!empty($workshop->latesubmissions); $workshop->phaseswitchassessment = (int)!empty($workshop->phaseswitchassessment); - // todo - if the grading strategy is being changed, we must replace all aggregated peer grades with nulls - // todo - if maximum grades are being changed, we should probably recalculate or invalidate them + // todo - if the grading strategy is being changed, we may want to replace all aggregated peer grades with nulls $DB->update_record('workshop', $workshop); $context = context_module::instance($workshop->coursemodule); @@ -156,6 +161,12 @@ function workshop_update_instance(stdclass $workshop) { $workshop->instructreviewersformat = $workshop->instructreviewerseditor['format']; } + if ($draftitemid = $workshop->conclusioneditor['itemid']) { + $workshop->conclusion = file_save_draft_area_files($draftitemid, $context->id, 'mod_workshop', 'conclusion', + 0, workshop::instruction_editors_options($context), $workshop->conclusioneditor['text']); + $workshop->conclusionformat = $workshop->conclusioneditor['format']; + } + // re-save the record with the replaced URLs in editor fields $DB->update_record('workshop', $workshop); @@ -1172,6 +1183,7 @@ function workshop_get_file_areas($course, $cm, $context) { $areas['instructreviewers'] = get_string('areainstructreviewers', 'workshop'); $areas['submission_content'] = get_string('areasubmissioncontent', 'workshop'); $areas['submission_attachment'] = get_string('areasubmissionattachment', 'workshop'); + $areas['conclusion'] = get_string('areaconclusion', 'workshop'); return $areas; } @@ -1182,7 +1194,7 @@ function workshop_get_file_areas($course, $cm, $context) { * Apart from module intro (handled by pluginfile.php automatically), workshop files may be * media inserted into submission content (like images) and submission attachments. For these two, * the fileareas submission_content and submission_attachment are used. - * Besides that, areas instructauthors and instructreviewers contain the media + * Besides that, areas instructauthors, instructreviewers and conclusion contain the media * embedded using the mod_form.php. * * @package mod_workshop @@ -1220,9 +1232,23 @@ function workshop_pluginfile($course, $cm, $context, $filearea, array $args, $fo // finally send the file send_stored_file($file, $lifetime, 0, $forcedownload, $options); - } - if ($filearea === 'instructreviewers') { + } else if ($filearea === 'instructreviewers') { + array_shift($args); // itemid is ignored here + $relativepath = implode('/', $args); + $fullpath = "/$context->id/mod_workshop/$filearea/0/$relativepath"; + + $fs = get_file_storage(); + if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) { + send_file_not_found(); + } + + $lifetime = isset($CFG->filelifetime) ? $CFG->filelifetime : 86400; + + // finally send the file + send_stored_file($file, $lifetime, 0, $forcedownload, $options); + + } else if ($filearea === 'conclusion') { array_shift($args); // itemid is ignored here $relativepath = implode('/', $args); $fullpath = "/$context->id/mod_workshop/$filearea/0/$relativepath"; @@ -1397,7 +1423,7 @@ function workshop_get_file_info($browser, $areas, $course, $cm, $context, $filea return new file_info_stored($browser, $context, $storedfile, $urlbase, $topvisiblename, true, true, false, false); } - if ($filearea == 'instructauthors' or $filearea == 'instructreviewers') { + if ($filearea == 'instructauthors' or $filearea == 'instructreviewers' or $filearea == 'conclusion') { // always only itemid 0 $filepath = is_null($filepath) ? '/' : $filepath; diff --git a/mod/workshop/locallib.php b/mod/workshop/locallib.php index 20c579d98e8..c3f2f998fd1 100644 --- a/mod/workshop/locallib.php +++ b/mod/workshop/locallib.php @@ -149,6 +149,12 @@ class workshop { /** @var bool automatically switch to the assessment phase after the submissions deadline */ public $phaseswitchassessment; + /** @var string conclusion text to be displayed at the end of the activity */ + public $conclusion; + + /** @var int format of the conclusion text */ + public $conclusionformat; + /** * @var workshop_strategy grading strategy instance * Do not use directly, get the instance using {@link workshop::grading_strategy_instance()} @@ -2800,6 +2806,19 @@ class workshop_user_plan implements renderable { $task->completed = 'info'; $phase->tasks['evaluateinfo'] = $task; } + + if (has_capability('moodle/course:manageactivities', $workshop->context, $userid)) { + $task = new stdclass(); + $task->title = get_string('taskconclusion', 'workshop'); + $task->link = $workshop->updatemod_url(); + if (trim($workshop->conclusion)) { + $task->completed = true; + } elseif ($workshop->phase >= workshop::PHASE_EVALUATION) { + $task->completed = false; + } + $phase->tasks['conclusion'] = $task; + } + $this->phases[workshop::PHASE_EVALUATION] = $phase; //--------------------------------------------------------- diff --git a/mod/workshop/mod_form.php b/mod/workshop/mod_form.php index b68f89c0cd0..3f0f3bb04c8 100644 --- a/mod/workshop/mod_form.php +++ b/mod/workshop/mod_form.php @@ -172,6 +172,14 @@ class mod_workshop_mod_form extends moodleform_mod { $mform->disabledIf('examplesmode', 'useexamples'); $mform->setAdvanced('examplesmode'); + // Miscellaneous settings + $mform->addElement('header', 'miscellaneoussettings', get_string('miscellaneoussettings', 'workshop')); + + $label = get_string('conclusion', 'workshop'); + $mform->addElement('editor', 'conclusioneditor', $label, null, + workshop::instruction_editors_options($this->context)); + $mform->addHelpButton('conclusioneditor', 'conclusion', 'workshop'); + // Access control ------------------------------------------------------------- $mform->addElement('header', 'accesscontrol', get_string('accesscontrol', 'workshop')); @@ -237,6 +245,14 @@ class mod_workshop_mod_form extends moodleform_mod { $data['instructreviewers']); $data['instructreviewerseditor']['format'] = $data['instructreviewersformat']; $data['instructreviewerseditor']['itemid'] = $draftitemid; + + $draftitemid = file_get_submitted_draft_itemid('conclusion'); + $data['conclusioneditor']['text'] = file_prepare_draft_area($draftitemid, $this->context->id, + 'mod_workshop', 'conclusion', 0, + workshop::instruction_editors_options($this->context), + $data['conclusion']); + $data['conclusioneditor']['format'] = $data['conclusionformat']; + $data['conclusioneditor']['itemid'] = $draftitemid; } else { // adding a new workshop instance $draftitemid = file_get_submitted_draft_itemid('instructauthors'); @@ -246,6 +262,10 @@ class mod_workshop_mod_form extends moodleform_mod { $draftitemid = file_get_submitted_draft_itemid('instructreviewers'); file_prepare_draft_area($draftitemid, null, 'mod_workshop', 'instructreviewers', 0); // no context yet, itemid not used $data['instructreviewerseditor'] = array('text' => '', 'format' => editors_get_preferred_format(), 'itemid' => $draftitemid); + + $draftitemid = file_get_submitted_draft_itemid('conclusion'); + file_prepare_draft_area($draftitemid, null, 'mod_workshop', 'conclusion', 0); // no context yet, itemid not used + $data['conclusioneditor'] = array('text' => '', 'format' => editors_get_preferred_format(), 'itemid' => $draftitemid); } } diff --git a/mod/workshop/version.php b/mod/workshop/version.php index 09b062539c0..7e6e66e2313 100644 --- a/mod/workshop/version.php +++ b/mod/workshop/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$module->version = 2012061700; // the current module version (YYYYMMDDXX) -$module->requires = 2012061700; // requires this Moodle version +$module->version = 2012102400; // the current module version (YYYYMMDDXX) +$module->requires = 2012101800; // requires this Moodle version $module->component = 'mod_workshop'; // full name of the plugin (used for diagnostics) $module->cron = 60; // give as a chance every minute diff --git a/mod/workshop/view.php b/mod/workshop/view.php index 43db74407a7..33fb780de32 100644 --- a/mod/workshop/view.php +++ b/mod/workshop/view.php @@ -512,6 +512,13 @@ case workshop::PHASE_EVALUATION: } break; case workshop::PHASE_CLOSED: + if (trim($workshop->conclusion)) { + $conclusion = file_rewrite_pluginfile_urls($workshop->conclusion, 'pluginfile.php', $workshop->context->id, + 'mod_workshop', 'conclusion', 0, workshop::instruction_editors_options($workshop->context)); + print_collapsible_region_start('', 'workshop-viewlet-conclusion', get_string('conclusion', 'workshop')); + echo $output->box(format_text($conclusion, $workshop->conclusionformat, array('overflowdiv'=>true)), array('generalbox', 'conclusion')); + print_collapsible_region_end(); + } if (has_capability('mod/workshop:viewallassessments', $PAGE->context)) { $perpage = get_user_preferences('workshop_perpage', 10); $groupid = groups_get_activity_group($workshop->cm, true);