From 6405b2549c3f00ec60b5c3a9da686006948d4e61 Mon Sep 17 00:00:00 2001 From: David Mudrak Date: Mon, 4 Jan 2010 17:49:23 +0000 Subject: [PATCH] Assessment dimensions now have unique id which allows to embed media. --- .../grading/accumulative/edit_form.php | 2 +- .../grading/accumulative/strategy.php | 110 +++++++++++------- mod/workshop/grading/lib.php | 43 +++++++ mod/workshop/index.php | 2 +- mod/workshop/mod_form.php | 29 +---- 5 files changed, 121 insertions(+), 65 deletions(-) diff --git a/mod/workshop/grading/accumulative/edit_form.php b/mod/workshop/grading/accumulative/edit_form.php index 13781ee91e..b7b1906ce5 100644 --- a/mod/workshop/grading/accumulative/edit_form.php +++ b/mod/workshop/grading/accumulative/edit_form.php @@ -57,7 +57,7 @@ class workshop_edit_accumulative_strategy_form extends workshop_edit_strategy_fo for ($i = 0; $i < $norepeats; $i++) { $mform->addElement('header', 'dimension'.$i, get_string('dimensionnumberaccumulative', 'workshop', $i+1)); - $mform->addElement('hidden', 'dimensionid__idx_'.$i); + $mform->addElement('hidden', 'dimensionid__idx_'.$i); // the id in workshop_forms_accumulative $mform->addElement('editor', 'description__idx_'.$i.'_editor', get_string('dimensiondescription', 'workshop'), array('cols' => 20), $descriptionopts); $mform->addElement('select', 'grade__idx_'.$i, get_string('grade'), $gradeoptions); diff --git a/mod/workshop/grading/accumulative/strategy.php b/mod/workshop/grading/accumulative/strategy.php index b14d550e22..c23eac13da 100644 --- a/mod/workshop/grading/accumulative/strategy.php +++ b/mod/workshop/grading/accumulative/strategy.php @@ -30,7 +30,7 @@ require_once(dirname(dirname(__FILE__)) . '/lib.php'); // interface definition /** * Accumulative grading strategy logic. */ -class workshop_accumulative_strategy implements workshop_strategy { +class workshop_accumulative_strategy extends workshop_base_strategy implements workshop_strategy { /** @var workshop the parent workshop instance */ protected $workshop; @@ -81,11 +81,13 @@ class workshop_accumulative_strategy implements workshop_strategy { $norepeats += WORKSHOP_STRATEGY_ADDDIMS; } - for ($i = 0; $i < $norepeats; $i++) { + // prepare the emebeded files + for ($i = 0; $i < $this->nodimensions; $i++) { // prepare all editor elements $fields = file_prepare_standard_editor($fields, 'description__idx_'.$i, $this->descriptionopts, - $PAGE->context, 'workshop_dimension_description', 0); + $PAGE->context, 'workshop_dimension_description', $fields->{'dimensionid__idx_'.$i}); } + $customdata = array(); $customdata['workshop'] = $this->workshop; $customdata['strategy'] = $this; @@ -103,7 +105,14 @@ class workshop_accumulative_strategy implements workshop_strategy { protected function load_fields() { global $DB; - $dims = $DB->get_records('workshop_forms_' . $this->name(), array('workshopid' => $this->workshop->id), 'sort'); + $sql = 'SELECT master.id,dim.description,dim.descriptionformat,dim.grade,dim.weight + FROM {workshop_forms} master + JOIN {workshop_forms_accumulative} dim ON (dim.id=master.localid) + WHERE master.workshopid = ? + ORDER BY master.sort'; + $params[0] = $this->workshop->id; + + $dims = $DB->get_records_sql($sql, $params); $this->nodimensions = count($dims); $fields = $this->_cook_dimension_records($dims); return $fields; @@ -120,18 +129,17 @@ class workshop_accumulative_strategy implements workshop_strategy { */ protected function _cook_dimension_records(array $raw) { - $formdata = array(); + $formdata = new stdClass(); $key = 0; foreach ($raw as $dimension) { - $formdata['dimensionid__idx_' . $key] = $dimension->id; - $formdata['description__idx_' . $key] = $dimension->description; - $formdata['descriptionformat__idx_' . $key] = $dimension->descriptionformat; - $formdata['grade__idx_' . $key] = $dimension->grade; - $formdata['weight__idx_' . $key] = $dimension->weight; + $formdata->{'dimensionid__idx_' . $key} = $dimension->id; + $formdata->{'description__idx_' . $key} = $dimension->description; + $formdata->{'description__idx_' . $key.'format'} = $dimension->descriptionformat; + $formdata->{'grade__idx_' . $key} = $dimension->grade; + $formdata->{'weight__idx_' . $key} = $dimension->weight; $key++; } - $cooked = (object)$formdata; - return $cooked; + return $formdata; } /** @@ -147,32 +155,50 @@ class workshop_accumulative_strategy implements workshop_strategy { * @return void */ public function save_edit_strategy_form(stdClass $data) { - global $DB; + global $DB, $PAGE; if (!isset($data->strategyname) || ($data->strategyname != $this->name())) { // the workshop strategy has changed since the form was opened for editing throw new moodle_exception('strategyhaschanged', 'workshop'); } - - $data = $this->_cook_edit_form_data($data); - $todelete = array(); - foreach ($data as $record) { - if (empty($record->description)) { - if (!empty($record->id)) { + $workshopid = $data->workshopid; + $norepeats = $data->norepeats; + + $data = $this->_cook_edit_form_data($data); + $masterrecords = $data->forms; + $localrecords = $data->forms_accumulative; + $todeletelocal = array(); // local ids to be deleted + $todeletemaster = array(); // master ids to be deleted + + for ($i=0; $i < $norepeats; $i++) { + $local = $localrecords[$i]; + $master = $masterrecords[$i]; + if (empty($local->description_editor['text'])) { + if (!empty($local->id)) { // existing record with empty description - to be deleted - $todelete[] = $record->id; + $todeletelocal[] = $local->id; + $todeletemaster[] = $this->dimension_master_id($local->id); } continue; } - if (empty($record->id)) { + if (empty($local->id)) { // new field - $record->id = $DB->insert_record('workshop_forms_' . $this->name(), $record); + $local->id = $DB->insert_record('workshop_forms_accumulative', $local); + $master->localid = $local->id; + $master->id = $DB->insert_record('workshop_forms', $master); } else { // exiting field - $DB->update_record('workshop_forms_' . $this->name(), $record); + $master->id = $this->dimension_master_id($local->id); + $DB->update_record('workshop_forms', $master); } + // $local record now has its id, let us re-save it with correct path to embeded media files + $local = file_postupdate_standard_editor($local, 'description', $this->descriptionopts, + $PAGE->context, 'workshop_dimension_description', $local->id); + $DB->update_record('workshop_forms_accumulative', $local); } - $DB->delete_records_list('workshop_forms_' . $this->name(), 'id', $todelete); + // todo unlink embedded files + $DB->delete_records_list('workshop_forms_accumulative', 'id', $todeletelocal); + $DB->delete_records_list('workshop_forms', 'id', $todeletemaster); } /** @@ -189,23 +215,27 @@ class workshop_accumulative_strategy implements workshop_strategy { protected function _cook_edit_form_data(stdClass $raw) { global $PAGE; - $cook = array(); + $cook = new stdClass(); // to be returned + $cook->forms = array(); // to be stored in {workshop_forms} + $cook->forms_accumulative = array(); // to be stored in {workshop_forms_accumulative} + for ($i = 0; $i < $raw->norepeats; $i++) { - $raw = file_postupdate_standard_editor($raw, 'description__idx_'.$i, $this->descriptionopts, - $PAGE->context, 'workshop_dimension_description', 0); - $cook[$i] = new stdClass(); - $fieldname = 'dimensionid__idx_'.$i; - $cook[$i]->id = isset($raw->$fieldname) ? $raw->$fieldname : null; - $cook[$i]->workshopid = $this->workshop->id; - $cook[$i]->sort = $i + 1; - $fieldname = 'description__idx_'.$i; - $cook[$i]->description = isset($raw->$fieldname) ? $raw->$fieldname : null; - $fieldname = 'description__idx_'.$i.'format'; - $cook[$i]->descriptionformat = isset($raw->$fieldname) ? $raw->$fieldname : FORMAT_HTML; - $fieldname = 'grade__idx_'.$i; - $cook[$i]->grade = isset($raw->$fieldname) ? $raw->$fieldname : null; - $fieldname = 'weight__idx_'.$i; - $cook[$i]->weight = isset($raw->$fieldname) ? $raw->$fieldname : null; + $cook->forms_accumulative[$i] = new stdClass(); + $fieldname = 'dimensionid__idx_'.$i; + $cook->forms_accumulative[$i]->id = isset($raw->$fieldname) ? $raw->$fieldname : null; + $fieldname = 'description__idx_'.$i.'_editor'; + $cook->forms_accumulative[$i]->description_editor = isset($raw->$fieldname) ? $raw->$fieldname : null; + $fieldname = 'grade__idx_'.$i; + $cook->forms_accumulative[$i]->grade = isset($raw->$fieldname) ? $raw->$fieldname : null; + $fieldname = 'weight__idx_'.$i; + $cook->forms_accumulative[$i]->weight = isset($raw->$fieldname) ? $raw->$fieldname : null; + + $cook->forms[$i] = new stdClass(); + $cook->forms[$i]->id = null; // will be checked later, considered unknown at the moment + $cook->forms[$i]->workshopid = $this->workshop->id; + $cook->forms[$i]->sort = $i + 1; + $cook->forms[$i]->strategy = 'accumulative'; + $cook->forms[$i]->dimensionid = $cook->forms_accumulative[$i]->id; } return $cook; } diff --git a/mod/workshop/grading/lib.php b/mod/workshop/grading/lib.php index b76cf02e76..36f0d9d65b 100644 --- a/mod/workshop/grading/lib.php +++ b/mod/workshop/grading/lib.php @@ -81,3 +81,46 @@ interface workshop_strategy { */ public function save_assessment(stdClass $assessment, stdClass $data); } + +/** + * Provides common methods for all grading strategies + * + * @copyright 2009 David Mudrak + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class workshop_base_strategy { + + /** + * Returns the dimension's master id from table {workshop_forms} + * + * Every grading strategy defines its assessment dimensions in its own tables (eg workshop_forms_accumulative). + * But we need a unique identifier across all strategies to be able to embed media into dimension descriptions. + * So, every dimension has to have a record in the master table workshop_forms. This is a similar pattern + * to what Moodle already uses with course_modules and instances. + * + * @param int $localid The id if the dimension in the subplugin table (eg workshop_forms_accumulative) + * @return int|false The master id from workshop_forms_accumulative or false, if not found + */ + public function dimension_master_id($localid) { + global $DB; + /** @var array Cache database query results so we can call from a loop */ + static $cache=null; + + if (is_null($cache)) { + $strategy = $this->name(); + $dimids = $DB->get_records('workshop_forms', + array('workshopid' => $this->workshop->id, 'strategy' => 'accumulative'), '', 'id,localid'); + $cache = array(); + foreach ($dimids as $masterid => $master) { + $cache[$masterid] = $master->localid; + } + $cache = array_flip($cache); + // now the $cache contains records [$localid] => [$masterid] + } + + if (isset($cache[$localid])) { + return $localid; + } + return false; + } +} diff --git a/mod/workshop/index.php b/mod/workshop/index.php index c1decbbde7..3edeb398e4 100644 --- a/mod/workshop/index.php +++ b/mod/workshop/index.php @@ -60,7 +60,7 @@ echo $OUTPUT->header($navigation); if (! $workshops = get_all_instances_in_course('workshop', $course)) { echo $OUTPUT->heading(get_string('noworkshops', 'workshop'), 2); - echo $OUTPUT->continue_button("view.php?id=$course->id"); + echo $OUTPUT->continue_button(new moodle_url($CFG->wwwroot . '/course/view.php', array('id' => $course->id))); echo $OUTPUT->footer(); die(); } diff --git a/mod/workshop/mod_form.php b/mod/workshop/mod_form.php index 804285e03d..95c7934e39 100644 --- a/mod/workshop/mod_form.php +++ b/mod/workshop/mod_form.php @@ -98,12 +98,6 @@ class mod_workshop_mod_form extends moodleform_mod { /// Submission settings -------------------------------------------------------- $mform->addElement('header', 'submissionsettings', get_string('submissionsettings', 'workshop')); - $label = get_string('latesubmissions', 'workshop'); - $text = get_string('latesubmissionsdesc', 'workshop'); - $mform->addElement('advcheckbox', 'latesubmissions', $label, $text); - $mform->setHelpButton('latesubmissions', array('latesubmissions', $label, 'workshop')); - $mform->setAdvanced('latesubmissions'); - $options = array(); for ($i=7; $i>=0; $i--) { $options[$i] = $i; @@ -112,24 +106,21 @@ class mod_workshop_mod_form extends moodleform_mod { $mform->addElement('select', 'nattachments', $label, $options); $mform->setDefault('nattachments', 1); $mform->setHelpButton('nattachments', array('nattachments', $label, 'workshop')); - $mform->setAdvanced('nattachments'); + + $label = get_string('latesubmissions', 'workshop'); + $text = get_string('latesubmissionsdesc', 'workshop'); + $mform->addElement('advcheckbox', 'latesubmissions', $label, $text); + $mform->setHelpButton('latesubmissions', array('latesubmissions', $label, 'workshop')); $options = get_max_upload_sizes($CFG->maxbytes, $COURSE->maxbytes); $options[0] = get_string('courseuploadlimit') . ' ('.display_size($COURSE->maxbytes).')'; $mform->addElement('select', 'maxbytes', get_string('maximumsize', 'assignment'), $options); $mform->setDefault('maxbytes', $workshopconfig->maxbytes); $mform->setHelpButton('maxbytes', array('maxbytes', $label, 'workshop')); - $mform->setAdvanced('maxbytes'); /// Assessment settings $mform->addElement('header', 'assessmentsettings', get_string('assessmentsettings', 'workshop')); - $label = get_string('nsassessments', 'workshop'); - $options = workshop_get_numbers_of_assessments(); - $mform->addElement('select', 'nsassessments', $label, $options); - $mform->setDefault('nsassessments', $workshopconfig->nsassessments); - $mform->setHelpButton('nsassessments', array('nsassessments', $label, 'workshop')); - $label = get_string('nexassessments', 'workshop'); $options = workshop_get_numbers_of_assessments(); $options[0] = get_string('assessallexamples', 'workshop'); @@ -138,17 +129,12 @@ class mod_workshop_mod_form extends moodleform_mod { $mform->setHelpButton('nexassessments', array('nexassessments', $label, 'workshop')); $mform->disabledIf('nexassessments', 'useexamples'); - $label = get_string('assesswosubmission', 'workshop'); - $text = get_string('assesswosubmissiondesc', 'workshop'); - $mform->addElement('advcheckbox', 'assesswosubmission', $label, $text); - $mform->setHelpButton('assesswosubmission', array('assesswosubmission', $label, 'workshop')); - $mform->setAdvanced('assesswosubmission'); - $label = get_string('examplesmode', 'workshop'); $options = workshop_get_example_modes(); $mform->addElement('select', 'examplesmode', $label, $options); $mform->setDefault('examplesmode', $workshopconfig->examplesmode); $mform->setHelpButton('examplesmode', array('examplesmode', $label, 'workshop')); + $mform->disabledIf('nexassessments', 'useexamples'); $mform->setAdvanced('examplesmode'); $label = get_string('teacherweight', 'workshop'); @@ -156,7 +142,6 @@ class mod_workshop_mod_form extends moodleform_mod { $mform->addElement('select', 'teacherweight', $label, $options); $mform->setDefault('teacherweight', 1); $mform->setHelpButton('teacherweight', array('teacherweight', $label, 'workshop')); - $mform->setAdvanced('teacherweight'); $label = get_string('agreeassessments', 'workshop'); $text = get_string('agreeassessmentsdesc', 'workshop'); @@ -172,7 +157,6 @@ class mod_workshop_mod_form extends moodleform_mod { $mform->addElement('select', 'assessmentcomps', $label, $levels); $mform->setDefault('assessmentcomps', $workshopconfig->assessmentcomps); $mform->setHelpButton('assessmentcomps', array('assessmentcomps', $label, 'workshop')); - $mform->setAdvanced('assessmentcomps'); /// Access control $mform->addElement('header', 'accesscontrol', get_string('accesscontrol', 'workshop')); @@ -206,7 +190,6 @@ class mod_workshop_mod_form extends moodleform_mod { $mform->addElement('passwordunmask', 'password', $label); $mform->setType('quizpassword', PARAM_TEXT); $mform->setHelpButton('password', array('requirepassword', $label, 'workshop')); - $mform->setAdvanced('password'); /// Common module settinga, Restrict availability, Activity completion etc. ---- $features = array('groups'=>true, 'groupings'=>true, 'groupmembersonly'=>true, -- 2.39.5