mirror of
https://github.com/moodle/moodle.git
synced 2025-01-18 22:08:20 +01:00
MDL-30112: marking rubric filling instances for regrading
- If a used rubric being updated, teacher (moderator) is notified - If the changes are significant, all instances automatically marked for regrade - if the changes are minor (texts, options or sortorder), teacher can choose whether to mark for regrade or not - The instances marked for regrade can be re-graded but students are not able to see the rubric - when grading a message appears if the instance is marked for regrade and is not visible to students
This commit is contained in:
parent
dd736a87ee
commit
0136124e21
@ -56,6 +56,9 @@ abstract class gradingform_controller {
|
||||
/** @var array graderange array of valid grades for this area. Use set_grade_range and get_grade_range to access this */
|
||||
private $graderange = null;
|
||||
|
||||
/** @var boolean|null cached result of function has_active_instances() */
|
||||
protected $hasactiveinstances = null;
|
||||
|
||||
/**
|
||||
* Do not instantinate this directly, use {@link grading_manager::get_controller()}
|
||||
*
|
||||
@ -334,8 +337,8 @@ abstract class gradingform_controller {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ACTIVE instance for this definition for the specified $raterid and $itemid
|
||||
* (if multiple raters are allowed, or only for $itemid otherwise).
|
||||
* Returns the current instance (either with status ACTIVE or NEEDUPDATE) for this definition for the
|
||||
* specified $raterid and $itemid (if multiple raters are allowed, or only for $itemid otherwise).
|
||||
*
|
||||
* @param int $raterid
|
||||
* @param int $itemid
|
||||
@ -344,19 +347,22 @@ abstract class gradingform_controller {
|
||||
*/
|
||||
public function get_current_instance($raterid, $itemid, $idonly = false) {
|
||||
global $DB;
|
||||
$select = array(
|
||||
$params = array(
|
||||
'formid' => $this->definition->id,
|
||||
'itemid' => $itemid,
|
||||
'status' => gradingform_instance::INSTANCE_STATUS_ACTIVE);
|
||||
'status1' => gradingform_instance::INSTANCE_STATUS_ACTIVE,
|
||||
'status2' => gradingform_instance::INSTANCE_STATUS_NEEDUPDATE);
|
||||
$select = 'formid=:formid and itemid=:itemid and (status=:status1 or status=:status2)';
|
||||
if (false /* TODO $manager->allow_multiple_raters() */) {
|
||||
$select['raterid'] = $raterid;
|
||||
$select .= ' and raterid=:raterid';
|
||||
$params['raterid'] = $raterid;
|
||||
}
|
||||
if ($idonly) {
|
||||
if ($current = $DB->get_record('grading_instances', $select, 'id', IGNORE_MISSING)) {
|
||||
if ($current = $DB->get_record_select('grading_instances', $select, $params, 'id', IGNORE_MISSING)) {
|
||||
return $current->id;
|
||||
}
|
||||
} else {
|
||||
if ($current = $DB->get_record('grading_instances', $select, '*', IGNORE_MISSING)) {
|
||||
if ($current = $DB->get_record_select('grading_instances', $select, $params, '*', IGNORE_MISSING)) {
|
||||
return $this->get_instance($current);
|
||||
}
|
||||
}
|
||||
@ -364,12 +370,13 @@ abstract class gradingform_controller {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of active instances for the specified $itemid
|
||||
* Returns list of ACTIVE instances for the specified $itemid
|
||||
* (intentionally does not return instances with status NEEDUPDATE)
|
||||
*
|
||||
* @param int $itemid
|
||||
* @return array of gradingform_instance objects
|
||||
*/
|
||||
public function get_current_instances($itemid) {
|
||||
public function get_active_instances($itemid) {
|
||||
global $DB;
|
||||
$conditions = array('formid' => $this->definition->id,
|
||||
'itemid' => $itemid,
|
||||
@ -382,6 +389,22 @@ abstract class gradingform_controller {
|
||||
return $rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if there are already people who has been graded on this definition.
|
||||
* In this case plugins may restrict changes of the grading definition
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function has_active_instances() {
|
||||
global $DB;
|
||||
if ($this->hasactiveinstances === null) {
|
||||
$conditions = array('formid' => $this->definition->id,
|
||||
'status' => gradingform_instance::INSTANCE_STATUS_ACTIVE);
|
||||
$this->hasactiveinstances = $DB->record_exists('grading_instances', $conditions);
|
||||
}
|
||||
return $this->hasactiveinstances;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the object of type gradingform_XXX_instance (where XXX is the plugin method name)
|
||||
*
|
||||
@ -528,9 +551,10 @@ abstract class gradingform_controller {
|
||||
* @param int $itemid
|
||||
* @param array $grading_info result of function grade_get_grades if plugin want to use some of their info
|
||||
* @param string $defaultcontent default string to be returned if no active grading is found or for some reason can not be shown to a user
|
||||
* @param boolean $cangrade whether current user has capability to grade in this context
|
||||
* @return string
|
||||
*/
|
||||
public function render_grade($page, $itemid, $grading_info, $defaultcontent) {
|
||||
public function render_grade($page, $itemid, $grading_info, $defaultcontent, $cangrade) {
|
||||
return $defaultcontent;
|
||||
}
|
||||
|
||||
@ -563,6 +587,7 @@ abstract class gradingform_controller {
|
||||
*/
|
||||
abstract class gradingform_instance {
|
||||
const INSTANCE_STATUS_ACTIVE = 1;
|
||||
const INSTANCE_STATUS_NEEDUPDATE = 2;
|
||||
const INSTANCE_STATUS_INCOMPLETE = 0;
|
||||
const INSTANCE_STATUS_ARCHIVE = 3;
|
||||
|
||||
@ -624,6 +649,19 @@ abstract class gradingform_instance {
|
||||
return $instanceid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current (active or needupdate) instance for the same raterid and itemid as this
|
||||
* instance. This function is useful to find the status of the currently modified instance
|
||||
*
|
||||
* @return gradingform_instance
|
||||
*/
|
||||
public function get_current_instance() {
|
||||
if ($this->get_status() == self::INSTANCE_STATUS_ACTIVE || $this->get_status() == self::INSTANCE_STATUS_NEEDUPDATE) {
|
||||
return $this;
|
||||
}
|
||||
return $this->get_controller()->get_current_instance($this->data->raterid, $this->data->itemid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the controller
|
||||
*
|
||||
@ -642,6 +680,15 @@ abstract class gradingform_instance {
|
||||
return $this->data->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns instance status
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function get_status() {
|
||||
return $this->data->status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the instance as ACTIVE and current active instance (if exists) as ARCHIVE
|
||||
*/
|
||||
@ -655,14 +702,10 @@ abstract class gradingform_instance {
|
||||
throw new coding_exception('You cannot mark active the grading instance without itemid');
|
||||
}
|
||||
$currentid = $this->get_controller()->get_current_instance($this->data->raterid, $this->data->itemid, true);
|
||||
if ($currentid) {
|
||||
if ($currentid != $this->get_id()) {
|
||||
$DB->update_record('grading_instances', array('id' => $currentid, 'status' => self::INSTANCE_STATUS_ARCHIVE));
|
||||
$DB->update_record('grading_instances', array('id' => $this->get_id(), 'status' => self::INSTANCE_STATUS_ACTIVE));
|
||||
}
|
||||
} else {
|
||||
$DB->update_record('grading_instances', array('id' => $this->get_id(), 'status' => self::INSTANCE_STATUS_ACTIVE));
|
||||
if ($currentid && $currentid != $this->get_id()) {
|
||||
$DB->update_record('grading_instances', array('id' => $currentid, 'status' => self::INSTANCE_STATUS_ARCHIVE));
|
||||
}
|
||||
$DB->update_record('grading_instances', array('id' => $this->get_id(), 'status' => self::INSTANCE_STATUS_ACTIVE));
|
||||
$this->data->status = self::INSTANCE_STATUS_ACTIVE;
|
||||
}
|
||||
|
||||
|
@ -44,16 +44,16 @@ $PAGE->set_url(new moodle_url('/grade/grading/form/rubric/edit.php', array('area
|
||||
$PAGE->set_title(get_string('definerubric', 'gradingform_rubric'));
|
||||
$PAGE->set_heading(get_string('definerubric', 'gradingform_rubric'));
|
||||
|
||||
$mform = new gradingform_rubric_editrubric(null, array('areaid' => $areaid, 'context' => $context));
|
||||
$mform = new gradingform_rubric_editrubric(null, array('areaid' => $areaid, 'context' => $context, 'allowdraft' => !$controller->has_active_instances()));
|
||||
$data = $controller->get_definition_for_editing();
|
||||
$returnurl = optional_param('returnurl', $manager->get_management_url(), PARAM_LOCALURL);
|
||||
$data->returnurl = $returnurl;
|
||||
$mform->set_data($data);
|
||||
if ($mform->is_cancelled()) {
|
||||
redirect($returnurl);
|
||||
} else if ($mform->is_submitted() && $mform->is_validated()) {
|
||||
$data = $mform->get_data();
|
||||
$controller->update_definition($data);
|
||||
} else if ($mform->is_submitted() && $mform->is_validated() && !$mform->need_confirm_regrading($controller)) {
|
||||
// everything ok, validated, re-grading confirmed if needed. Make changes to the rubric
|
||||
$controller->update_definition($mform->get_data());
|
||||
redirect($returnurl);
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,12 @@ class gradingform_rubric_editrubric extends moodleform {
|
||||
|
||||
$buttonarray = array();
|
||||
$buttonarray[] = &$form->createElement('submit', 'saverubric', get_string('saverubric', 'gradingform_rubric'));
|
||||
$buttonarray[] = &$form->createElement('submit', 'saverubricdraft', get_string('saverubricdraft', 'gradingform_rubric'));
|
||||
if ($this->_customdata['allowdraft']) {
|
||||
$buttonarray[] = &$form->createElement('submit', 'saverubricdraft', get_string('saverubricdraft', 'gradingform_rubric'));
|
||||
}
|
||||
$editbutton = &$form->createElement('submit', 'editrubric', ' ');
|
||||
$editbutton->freeze();
|
||||
$buttonarray[] = &$editbutton;
|
||||
$buttonarray[] = &$form->createElement('cancel');
|
||||
$form->addGroup($buttonarray, 'buttonar', '', array(' '), false);
|
||||
$form->closeHeaderBefore('buttonar');
|
||||
@ -93,6 +98,9 @@ class gradingform_rubric_editrubric extends moodleform {
|
||||
if ($rubricel->non_js_button_pressed($data['rubric'])) {
|
||||
// if JS is disabled and button such as 'Add criterion' is pressed - prevent from submit
|
||||
$err['rubricdummy'] = 1;
|
||||
} else if (isset($data['editrubric'])) {
|
||||
// continue editing
|
||||
$err['rubricdummy'] = 1;
|
||||
} else if (isset($data['saverubric']) && $data['saverubric']) {
|
||||
// If user attempts to make rubric active - it needs to be validated
|
||||
if ($rubricel->validate($data['rubric']) !== false) {
|
||||
@ -117,4 +125,70 @@ class gradingform_rubric_editrubric extends moodleform {
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if there are changes in the rubric and it is needed to ask user whether to
|
||||
* mark the current grades for re-grading. User may confirm re-grading and continue,
|
||||
* return to editing or cancel the changes
|
||||
*
|
||||
* @param gradingform_rubric_controller $controller
|
||||
*/
|
||||
function need_confirm_regrading($controller) {
|
||||
$data = $this->get_data();
|
||||
if (isset($data->rubric['regrade'])) {
|
||||
// we have already displayed the confirmation on the previous step
|
||||
return false;
|
||||
}
|
||||
if (!isset($data->saverubric) || !$data->saverubric) {
|
||||
// we only need confirmation when button 'Save rubric' is pressed
|
||||
return false;
|
||||
}
|
||||
if (!$controller->has_active_instances()) {
|
||||
// nothing to re-grade, confirmation not needed
|
||||
return false;
|
||||
}
|
||||
$changelevel = $controller->update_or_check_rubric($data);
|
||||
if ($changelevel == 0) {
|
||||
// no changes in the rubric, no confirmation needed
|
||||
return false;
|
||||
}
|
||||
|
||||
// freeze form elements and pass the values in hidden fields
|
||||
// TODO description_editor does not freeze the normal way!
|
||||
$form = $this->_form;
|
||||
foreach (array('rubric', 'name'/*, 'description_editor'*/) as $fieldname) {
|
||||
$el =& $form->getElement($fieldname);
|
||||
$el->freeze();
|
||||
$el->setPersistantFreeze(true);
|
||||
if ($fieldname == 'rubric') {
|
||||
$el->add_regrade_confirmation($changelevel);
|
||||
}
|
||||
}
|
||||
|
||||
// replace button text 'saverubric' and unfreeze 'Back to edit' button
|
||||
$this->findButton('saverubric')->setValue(get_string('continue'));
|
||||
$el =& $this->findButton('editrubric');
|
||||
$el->setValue(get_string('backtoediting', 'gradingform_rubric'));
|
||||
$el->unfreeze();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a form element (submit button) with the name $elementname
|
||||
*
|
||||
* @param string $elementname
|
||||
* @return HTML_QuickForm_element
|
||||
*/
|
||||
function &findButton($elementname) {
|
||||
$form = $this->_form;
|
||||
$buttonar =& $form->getElement('buttonar');
|
||||
$elements =& $buttonar->getElements();
|
||||
foreach ($elements as $el) {
|
||||
if ($el->getName() == $elementname) {
|
||||
return $el;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -69,3 +69,18 @@ $string['err_nodescription'] = 'Criterion description can not be empty';
|
||||
$string['err_nodefinition'] = 'Level definition can not be empty';
|
||||
$string['err_scoreformat'] = 'Number of points for each level must be a valid non-negative number';
|
||||
$string['err_totalscore'] = 'Maximum number of points possible when graded by the rubric must be more than zero';
|
||||
|
||||
$string['regrademessage1'] = 'You are about to save changes to the rubric that has already been used for grading. Please indicate whether your changes
|
||||
are significant and students grades need to be reviewed.
|
||||
If students already graded are marked for re-grading their
|
||||
current grades remain in gradebook but the students will not see the rubric grading before teacher updates it.';
|
||||
$string['regrademessage5'] = 'You are about to save significant changes to the rubric that has already been used for grading. Please note that all students already graded will be marked for re-grading.
|
||||
The
|
||||
current grades remain in gradebook but the students will not see the rubric grading before teacher updates it.';
|
||||
$string['regradeoption0'] = 'Do not mark for regrade';
|
||||
$string['regradeoption1'] = 'Mark for regrade';
|
||||
|
||||
$string['needregrademessage'] = 'Rubric definition was changed after this student had been graded. You must update the grade otherwise it will not be shown to student.';
|
||||
$string['rubricnotcompleted'] = 'You have to select a feedback on each rubric criterion';
|
||||
|
||||
$string['backtoediting'] = 'Back to editing';
|
@ -65,10 +65,36 @@ class gradingform_rubric_controller extends gradingform_controller {
|
||||
* @param int|null $usermodified optional userid of the author of the definition, defaults to the current user
|
||||
*/
|
||||
public function update_definition(stdClass $newdefinition, $usermodified = null) {
|
||||
$this->update_or_check_rubric($newdefinition, $usermodified, true);
|
||||
if (isset($newdefinition->rubric['regrade']) && $newdefinition->rubric['regrade']) {
|
||||
$this->mark_for_regrade();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Either saves the rubric definition into the database or check if it has been changed.
|
||||
* Returns the level of changes:
|
||||
* 0 - no changes
|
||||
* 1 - only texts or criteria sortorders are changed, students probably do not require re-grading
|
||||
* 2 - added levels but maximum score on rubric is the same, students still may not require re-grading
|
||||
* 3 - removed criteria or added levels or changed number of points, students require re-grading but may be re-graded automatically
|
||||
* 4 - removed levels - students require re-grading and not all students may be re-graded automatically
|
||||
* 5 - added criteria - all students require manual re-grading
|
||||
*
|
||||
* @param stdClass $newdefinition rubric definition data as coming from gradingform_rubric_editrubric::get_data()
|
||||
* @param int|null $usermodified optional userid of the author of the definition, defaults to the current user
|
||||
* @param boolean $doupdate if true actually updates DB, otherwise performs a check
|
||||
*
|
||||
*/
|
||||
public function update_or_check_rubric(stdClass $newdefinition, $usermodified = null, $doupdate = false) {
|
||||
global $DB;
|
||||
|
||||
// firstly update the common definition data in the {grading_definition} table
|
||||
if ($this->definition === false) {
|
||||
if (!$doupdate) {
|
||||
// if we create the new definition there is no such thing as re-grading anyway
|
||||
return 5;
|
||||
}
|
||||
// if definition does not exist yet, create a blank one
|
||||
// (we need id to save files embedded in description)
|
||||
parent::update_definition(new stdClass(), $usermodified);
|
||||
@ -81,13 +107,12 @@ class gradingform_rubric_controller extends gradingform_controller {
|
||||
$editoroptions = self::description_form_field_options($this->get_context());
|
||||
$newdefinition = file_postupdate_standard_editor($newdefinition, 'description', $editoroptions, $this->get_context(),
|
||||
'gradingform_rubric', 'definition_description', $this->definition->id);
|
||||
parent::update_definition($newdefinition, $usermodified);
|
||||
|
||||
// reload the definition from the database
|
||||
$currentdefinition = $this->get_definition(true);
|
||||
|
||||
// update rubric data
|
||||
$haschanges = false;
|
||||
$haschanges = array();
|
||||
if (empty($newdefinition->rubric['criteria'])) {
|
||||
$newcriteria = array();
|
||||
} else {
|
||||
@ -102,6 +127,7 @@ class gradingform_rubric_controller extends gradingform_controller {
|
||||
if (array_key_exists('levels', $criterion)) {
|
||||
$levelsdata = $criterion['levels'];
|
||||
}
|
||||
$criterionmaxscore = null;
|
||||
if (preg_match('/^NEWID\d+$/', $id)) {
|
||||
// insert criterion into DB
|
||||
$data = array('formid' => $this->definition->id, 'descriptionformat' => FORMAT_MOODLE); // TODO format is not supported yet
|
||||
@ -110,8 +136,10 @@ class gradingform_rubric_controller extends gradingform_controller {
|
||||
$data[$key] = $criterion[$key];
|
||||
}
|
||||
}
|
||||
$id = $DB->insert_record('gradingform_rubric_criteria', $data);
|
||||
$haschanges = true;
|
||||
if ($doupdate) {
|
||||
$id = $DB->insert_record('gradingform_rubric_criteria', $data);
|
||||
}
|
||||
$haschanges[5] = true;
|
||||
} else {
|
||||
// update criterion in DB
|
||||
$data = array();
|
||||
@ -123,14 +151,21 @@ class gradingform_rubric_controller extends gradingform_controller {
|
||||
if (!empty($data)) {
|
||||
// update only if something is changed
|
||||
$data['id'] = $id;
|
||||
$DB->update_record('gradingform_rubric_criteria', $data);
|
||||
$haschanges = true;
|
||||
if ($doupdate) {
|
||||
$DB->update_record('gradingform_rubric_criteria', $data);
|
||||
}
|
||||
$haschanges[1] = true;
|
||||
}
|
||||
// remove deleted levels from DB
|
||||
foreach (array_keys($currentcriteria[$id]['levels']) as $levelid) {
|
||||
// remove deleted levels from DB and calculate the maximum score for this criteria
|
||||
foreach ($currentcriteria[$id]['levels'] as $levelid => $currentlevel) {
|
||||
if ($criterionmaxscore === null || $criterionmaxscore < $currentlevel['score']) {
|
||||
$criterionmaxscore = $currentlevel['score'];
|
||||
}
|
||||
if (!array_key_exists($levelid, $levelsdata)) {
|
||||
$DB->delete_records('gradingform_rubric_levels', array('id' => $levelid));
|
||||
$haschanges = true;
|
||||
if ($doupdate) {
|
||||
$DB->delete_records('gradingform_rubric_levels', array('id' => $levelid));
|
||||
}
|
||||
$haschanges[4] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -150,8 +185,15 @@ class gradingform_rubric_controller extends gradingform_controller {
|
||||
$data[$key] = $level[$key];
|
||||
}
|
||||
}
|
||||
$levelid = $DB->insert_record('gradingform_rubric_levels', $data);
|
||||
$haschanges = true;
|
||||
if ($doupdate) {
|
||||
$levelid = $DB->insert_record('gradingform_rubric_levels', $data);
|
||||
}
|
||||
if ($criterionmaxscore !== null && $criterionmaxscore >= $level['score']) {
|
||||
// new level is added but the maximum score for this criteria did not change, re-grading may not be necessary
|
||||
$haschanges[2] = true;
|
||||
} else {
|
||||
$haschanges[3] = true;
|
||||
}
|
||||
} else {
|
||||
// update level in DB
|
||||
$data = array();
|
||||
@ -163,8 +205,13 @@ class gradingform_rubric_controller extends gradingform_controller {
|
||||
if (!empty($data)) {
|
||||
// update only if something is changed
|
||||
$data['id'] = $levelid;
|
||||
$DB->update_record('gradingform_rubric_levels', $data);
|
||||
$haschanges = true;
|
||||
if ($doupdate) {
|
||||
$DB->update_record('gradingform_rubric_levels', $data);
|
||||
}
|
||||
if (isset($data['score'])) {
|
||||
$haschanges[3] = true;
|
||||
}
|
||||
$haschanges[1] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -172,12 +219,41 @@ class gradingform_rubric_controller extends gradingform_controller {
|
||||
// remove deleted criteria from DB
|
||||
foreach (array_keys($currentcriteria) as $id) {
|
||||
if (!array_key_exists($id, $newcriteria)) {
|
||||
$DB->delete_records('gradingform_rubric_criteria', array('id' => $id));
|
||||
$DB->delete_records('gradingform_rubric_levels', array('criterionid' => $id));
|
||||
$haschanges = true;
|
||||
if ($doupdate) {
|
||||
$DB->delete_records('gradingform_rubric_criteria', array('id' => $id));
|
||||
$DB->delete_records('gradingform_rubric_levels', array('criterionid' => $id));
|
||||
}
|
||||
$haschanges[3] = true;
|
||||
}
|
||||
}
|
||||
$this->load_definition();
|
||||
foreach (array('status', 'description', 'descriptionformat', 'name', 'options') as $key) {
|
||||
if (isset($newdefinition->$key) && $newdefinition->$key != $this->definition->$key) {
|
||||
$haschanges[1] = true;
|
||||
}
|
||||
}
|
||||
if ($usermodified && $usermodified != $this->definition->usermodified) {
|
||||
$haschanges[1] = true;
|
||||
}
|
||||
if (!count($haschanges)) {
|
||||
return 0;
|
||||
}
|
||||
if ($doupdate) {
|
||||
parent::update_definition($newdefinition, $usermodified);
|
||||
$this->load_definition();
|
||||
}
|
||||
// return the maximum level of changes
|
||||
$changelevels = array_keys($haschanges);
|
||||
sort($changelevels);
|
||||
return array_pop($changelevels);
|
||||
}
|
||||
|
||||
public function mark_for_regrade() {
|
||||
global $DB;
|
||||
if ($this->has_active_instances()) {
|
||||
$conditions = array('formid' => $this->definition->id,
|
||||
'status' => gradingform_instance::INSTANCE_STATUS_ACTIVE);
|
||||
$DB->set_field('grading_instances', 'status', gradingform_instance::INSTANCE_STATUS_NEEDUPDATE, $conditions);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -321,8 +397,6 @@ class gradingform_rubric_controller extends gradingform_controller {
|
||||
return $new;
|
||||
}
|
||||
|
||||
// TODO the following functions may be moved to parent:
|
||||
|
||||
/**
|
||||
* @return array options for the form description field
|
||||
*/
|
||||
@ -416,11 +490,11 @@ class gradingform_rubric_controller extends gradingform_controller {
|
||||
* @param int $itemid
|
||||
* @param array $grading_info result of function grade_get_grades
|
||||
* @param string $defaultcontent default string to be returned if no active grading is found
|
||||
* @param boolean $cangrade whether current user has capability to grade in this context
|
||||
* @return string
|
||||
*/
|
||||
public function render_grade($page, $itemid, $grading_info, $defaultcontent) {
|
||||
$instances = $this->get_current_instances($itemid);
|
||||
return $this->get_renderer($page)->display_instances($this->get_current_instances($itemid), $defaultcontent);
|
||||
public function render_grade($page, $itemid, $grading_info, $defaultcontent, $cangrade) {
|
||||
return $this->get_renderer($page)->display_instances($this->get_active_instances($itemid), $defaultcontent, $cangrade);
|
||||
}
|
||||
|
||||
//// full-text search support /////////////////////////////////////////////
|
||||
@ -508,7 +582,6 @@ class gradingform_rubric_instance extends gradingform_instance {
|
||||
* @return boolean true if the form data is validated and contains no errors
|
||||
*/
|
||||
public function validate_grading_element($elementvalue) {
|
||||
// TODO: if there is nothing selected in rubric, we don't enter this function at all :(
|
||||
$criteria = $this->get_controller()->get_definition()->rubric_criteria;
|
||||
if (!isset($elementvalue['criteria']) || !is_array($elementvalue['criteria']) || sizeof($elementvalue['criteria']) < sizeof($criteria)) {
|
||||
return false;
|
||||
@ -554,12 +627,15 @@ class gradingform_rubric_instance extends gradingform_instance {
|
||||
foreach ($data['criteria'] as $criterionid => $record) {
|
||||
if (!array_key_exists($criterionid, $currentgrade['criteria'])) {
|
||||
$newrecord = array('forminstanceid' => $this->get_id(), 'criterionid' => $criterionid,
|
||||
'levelid' => $record['levelid'], 'remark' => $record['remark'], 'remarkformat' => FORMAT_MOODLE);
|
||||
'levelid' => $record['levelid'], 'remarkformat' => FORMAT_MOODLE);
|
||||
if (isset($record['remark'])) {
|
||||
$newrecord['remark'] = $record['remark'];
|
||||
}
|
||||
$DB->insert_record('gradingform_rubric_fillings', $newrecord);
|
||||
} else {
|
||||
$newrecord = array('id' => $currentgrade['criteria'][$criterionid]['id']);
|
||||
foreach (array('levelid', 'remark'/*, 'remarkformat' TODO */) as $key) {
|
||||
if ($currentgrade['criteria'][$criterionid][$key] != $record[$key]) {
|
||||
if (isset($record[$key]) && $currentgrade['criteria'][$criterionid][$key] != $record[$key]) {
|
||||
$newrecord[$key] = $record[$key];
|
||||
}
|
||||
}
|
||||
@ -616,15 +692,6 @@ class gradingform_rubric_instance extends gradingform_instance {
|
||||
return round(($curscore-$minscore)/($maxscore-$minscore)*($maxgrade-$mingrade), 0) + $mingrade; // TODO mapping
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the error message displayed in case of validation failed
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function default_validation_error_message() {
|
||||
return 'The rubric is incomplete'; //TODO string
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns html for form element of type 'grading'.
|
||||
*
|
||||
@ -648,10 +715,18 @@ class gradingform_rubric_instance extends gradingform_instance {
|
||||
$criteria = $this->get_controller()->get_definition()->rubric_criteria;
|
||||
$options = $this->get_controller()->get_options();
|
||||
$value = $gradingformelement->getValue();
|
||||
$html = '';
|
||||
if ($value === null) {
|
||||
$value = $this->get_rubric_filling();
|
||||
} else if (!$this->validate_grading_element($value)) {
|
||||
$html .= html_writer::tag('div', get_string('rubricnotcompleted', 'gradingform_rubric'), array('class' => 'gradingform_rubric-error'));
|
||||
}
|
||||
return $this->get_controller()->get_renderer($page)->display_rubric($criteria, $options, $mode, $gradingformelement->getName(), $value);
|
||||
$currentinstance = $this->get_current_instance();
|
||||
if ($currentinstance && $currentinstance->get_status() == gradingform_instance::INSTANCE_STATUS_NEEDUPDATE) {
|
||||
$html .= html_writer::tag('div', get_string('needregrademessage', 'gradingform_rubric'), array('class' => 'gradingform_rubric-regrade'));
|
||||
}
|
||||
$html .= $this->get_controller()->get_renderer($page)->display_rubric($criteria, $options, $mode, $gradingformelement->getName(), $value);
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -296,16 +296,16 @@ class gradingform_rubric_renderer extends plugin_renderer_base {
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FROZEN && $value) {
|
||||
$html .= html_writer::empty_tag('input', $attrs + array('type' => 'hidden', 'value' => $value));
|
||||
}
|
||||
// Display option as checkbox
|
||||
$attrs['type'] = 'checkbox';
|
||||
$attrs['value'] = 1;
|
||||
if ($value) {
|
||||
$attrs['checked'] = 'checked';
|
||||
}
|
||||
if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FROZEN) {
|
||||
$attrs['disabled'] = 'disabled';
|
||||
}
|
||||
if ($mode == gradingform_rubric_controller::DISPLAY_PREVIEW) {
|
||||
if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FROZEN || $mode == gradingform_rubric_controller::DISPLAY_PREVIEW) {
|
||||
$attrs['disabled'] = 'disabled';
|
||||
unset($attrs['name']);
|
||||
}
|
||||
@ -391,14 +391,16 @@ class gradingform_rubric_renderer extends plugin_renderer_base {
|
||||
*
|
||||
* @param array $instances array of objects of type gradingform_rubric_instance
|
||||
* @param string $defaultcontent default string that would be displayed without advanced grading
|
||||
* @param boolean $cangrade whether current user has capability to grade in this context
|
||||
* @return string
|
||||
*/
|
||||
public function display_instances($instances, $defaultcontent) {
|
||||
public function display_instances($instances, $defaultcontent, $cangrade) {
|
||||
$rv = '';
|
||||
if (sizeof($instances)) {
|
||||
$rv = html_writer::start_tag('div', array('class' => 'advancedgrade'));
|
||||
$rv .= html_writer::start_tag('div', array('class' => 'advancedgrade'));
|
||||
$idx = 0;
|
||||
foreach ($instances as $instance) {
|
||||
$rv .= $this->display_instance($instance, $idx++);
|
||||
$rv .= $this->display_instance($instance, $idx++, $cangrade);
|
||||
}
|
||||
$rv .= html_writer::end_tag('div');
|
||||
}
|
||||
@ -410,12 +412,34 @@ class gradingform_rubric_renderer extends plugin_renderer_base {
|
||||
*
|
||||
* @param gradingform_rubric_instance $instance
|
||||
* @param int idx unique number of instance on page
|
||||
* @param boolean $cangrade whether current user has capability to grade in this context
|
||||
*/
|
||||
public function display_instance(gradingform_rubric_instance $instance, $idx) {
|
||||
public function display_instance(gradingform_rubric_instance $instance, $idx, $cangrade) {
|
||||
$criteria = $instance->get_controller()->get_definition()->rubric_criteria;
|
||||
$options = $instance->get_controller()->get_options();
|
||||
$values = $instance->get_rubric_filling();
|
||||
// TODO mode should be DISPLAY_REVIEW if this user is a teacher
|
||||
return $this->display_rubric($criteria, $options, gradingform_rubric_controller::DISPLAY_VIEW, 'rubric'.$idx, $values);
|
||||
if ($cangrade) {
|
||||
$mode = gradingform_rubric_controller::DISPLAY_REVIEW;
|
||||
} else {
|
||||
$mode = gradingform_rubric_controller::DISPLAY_VIEW;
|
||||
}
|
||||
return $this->display_rubric($criteria, $options, $mode, 'rubric'.$idx, $values);
|
||||
}
|
||||
|
||||
public function display_regrade_confirmation($elementname, $changelevel, $value) {
|
||||
$html = html_writer::start_tag('div', array('class' => 'gradingform_rubric-regrade'));
|
||||
if ($changelevel<=2) {
|
||||
$html .= get_string('regrademessage1', 'gradingform_rubric');
|
||||
$selectoptions = array(
|
||||
0 => get_string('regradeoption0', 'gradingform_rubric'),
|
||||
1 => get_string('regradeoption1', 'gradingform_rubric')
|
||||
);
|
||||
$html .= html_writer::select($selectoptions, $elementname.'[regrade]', $value, false);
|
||||
} else {
|
||||
$html .= get_string('regrademessage5', 'gradingform_rubric');
|
||||
$html .= html_writer::empty_tag('input', array('name' => $elementname.'[regrade]', 'value' => 1, 'type' => 'hidden'));
|
||||
}
|
||||
$html .= html_writer::end_tag('div');
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
|
@ -44,6 +44,23 @@ class MoodleQuickForm_rubriceditor extends HTML_QuickForm_input {
|
||||
return 'default';
|
||||
}
|
||||
|
||||
protected $regradeconfirmation = false;
|
||||
/**
|
||||
* Specifies that confirmation about re-grading needs to be added to this rubric editor.
|
||||
* $changelevel is saved in $this->regradeconfirmation and retrieved in toHtml()
|
||||
*
|
||||
* @see gradingform_rubric_controller::update_or_check_rubric()
|
||||
* @param int $changelevel
|
||||
*/
|
||||
function add_regrade_confirmation($changelevel) {
|
||||
$this->regradeconfirmation = $changelevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns html string to display this element
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function toHtml() {
|
||||
global $PAGE;
|
||||
$html = $this->_getTabs();
|
||||
@ -69,6 +86,12 @@ class MoodleQuickForm_rubriceditor extends HTML_QuickForm_input {
|
||||
$mode = gradingform_rubric_controller::DISPLAY_PREVIEW;
|
||||
}
|
||||
}
|
||||
if ($this->regradeconfirmation) {
|
||||
if (!isset($data['regrade'])) {
|
||||
$data['regrade'] = 1;
|
||||
}
|
||||
$html .= $renderer->display_regrade_confirmation($this->getName(), $this->regradeconfirmation, $data['regrade']);
|
||||
}
|
||||
if ($this->validationerrors) {
|
||||
$html .= $renderer->notification($this->validationerrors, 'error');
|
||||
}
|
||||
@ -114,6 +137,14 @@ class MoodleQuickForm_rubriceditor extends HTML_QuickForm_input {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (is_array($value)) {
|
||||
// for other array keys of $value no special treatmeant neeeded, copy them to return value as is
|
||||
foreach (array_keys($value) as $key) {
|
||||
if ($key != 'options' && $key != 'criteria') {
|
||||
$return[$key] = $value[$key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// iterate through criteria
|
||||
$lastaction = null;
|
||||
|
@ -107,4 +107,11 @@
|
||||
.gradingform_rubric .criterion .levels.error { border:1px solid red;}
|
||||
.gradingform_rubric .criterion .description.error,
|
||||
.gradingform_rubric .criterion .levels .level .definition.error,
|
||||
.gradingform_rubric .criterion .levels .level .score.error {background:#FFDDDD;}
|
||||
.gradingform_rubric .criterion .levels .level .score.error {background:#FFDDDD;}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
.gradingform_rubric-regrade {padding:10px;background:#FFDDDD;border:1px solid #F00;margin-bottom:10px;}
|
||||
.gradingform_rubric-error {color:red;font-weight:bold;}
|
||||
|
@ -335,7 +335,7 @@ class assignment_base {
|
||||
$grade_str = '<div class="grade">'. get_string("grade").': '.$grade->str_long_grade. '</div>';
|
||||
if (!empty($submission) && $controller = get_grading_manager($this->context, 'mod_assignment', 'submission')->get_active_controller()) {
|
||||
$controller->set_grade_range(make_grades_menu($this->assignment->grade));
|
||||
echo $controller->render_grade($PAGE, $submission->id, $item, $grade_str);
|
||||
echo $controller->render_grade($PAGE, $submission->id, $item, $grade_str, has_capability('mod/assignment:grade', $this->context));
|
||||
} else {
|
||||
echo $grade_str;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user