diff --git a/grade/grading/form/lib.php b/grade/grading/form/lib.php index 641baf394ce..bad66c8d5f5 100644 --- a/grade/grading/form/lib.php +++ b/grade/grading/form/lib.php @@ -50,6 +50,9 @@ abstract class gradingform_controller { /** @var stdClass|false the definition structure */ protected $definition; + /** @var array graderange array of valid grades for this area. Use set_grade_range and get_grade_range to access this */ + private $graderange = null; + /** * Do not instantinate this directly, use {@link grading_manager::get_controller()} * @@ -174,9 +177,10 @@ abstract class gradingform_controller { /** * Returns the grading form definition structure * + * @param boolean $force whether to force loading from DB even if it was already loaded * @return stdClass|false definition data or false if the form is not defined yet */ - public function get_definition() { + public function get_definition($force = false) { if (is_null($this->definition)) { $this->load_definition(); } @@ -459,12 +463,33 @@ abstract class gradingform_controller { * * @param moodle_page $page * @param int $itemid - * @param string $defaultcontent default string to be returned if no active grading is found + * @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 * @return string */ - public function render_grade($page, $itemid, $defaultcontent) { + public function render_grade($page, $itemid, $grading_info, $defaultcontent) { return $defaultcontent; } + + /** + * Sets the range of grades used in this area. This is usually either range like 0-100 + * or the scale where keys start from 1. Typical use: + * $controller->set_grade_range(make_grades_menu($gradingtype)); + */ + public final function set_grade_range(array $graderange) { + $this->graderange = $graderange; + } + + /** + * Returns the range of grades used in this area + * @return array + */ + public final function get_grade_range() { + if (empty($this->graderange)) { + return array(); + } + return $this->graderange; + } } /** @@ -600,7 +625,8 @@ abstract class gradingform_instance { /** * Calculates the grade to be pushed to the gradebook - * @return int the grade on 0-100 scale + * + * @return int the valid grade from $this->get_controller()->get_grade_range() */ abstract public function get_grade(); @@ -622,11 +648,12 @@ abstract class gradingform_instance { * If there are more than one input elements they MUST be elements of array with * name $gradingformelement->getName(). * Example: {NAME}[myelement1], {NAME}[myelement2][sub1], {NAME}[myelement2][sub2], etc. + * ( {NAME} is a shortcut for $gradingformelement->getName() ) * After submitting the form the value of $_POST[{NAME}] is passed to the functions * validate_grading_element() and submit_and_get_grade() * * Plugins may use $gradingformelement->getValue() to get the value passed on previous - * from submit + * form submit * * When forming html it is a plugin's responsibility to analyze flags * $gradingformelement->_flagFrozen and $gradingformelement->_persistantFreeze: diff --git a/grade/grading/form/rubric/edit.php b/grade/grading/form/rubric/edit.php index dee042d737b..721d3d87872 100644 --- a/grade/grading/form/rubric/edit.php +++ b/grade/grading/form/rubric/edit.php @@ -46,14 +46,13 @@ $PAGE->set_heading(get_string('definerubric', 'gradingform_rubric')); $PAGE->requires->js('/grade/grading/form/rubric/js/rubriceditor.js'); //TODO freeze rubric editor if needed -$mform = new gradingform_rubric_editrubric(null, array('areaid' => $areaid, 'freezerubric' => optional_param('freeze', 0, PARAM_INT))); +$mform = new gradingform_rubric_editrubric(null, array('areaid' => $areaid, 'context' => $context, 'freezerubric' => optional_param('freeze', 0, PARAM_INT))); $mform->set_data($controller->get_definition_for_editing()); if ($mform->is_cancelled()) { // todo process editing cancel in a better way redirect($manager->get_management_url()); } else if ($data = $mform->get_data()) { - $data = $controller->postupdate_definition_data($data); $controller->update_definition($data); redirect($PAGE->url); } diff --git a/grade/grading/form/rubric/edit_form.php b/grade/grading/form/rubric/edit_form.php index 14d52e3b29f..4170ff75bb2 100644 --- a/grade/grading/form/rubric/edit_form.php +++ b/grade/grading/form/rubric/edit_form.php @@ -50,7 +50,7 @@ class gradingform_rubric_editrubric extends moodleform { $form->setType('name', PARAM_TEXT); // description - $options = array(); + $options = gradingform_rubric_controller::description_form_field_options($this->_customdata['context']); $form->addElement('editor', 'description_editor', get_string('description', 'gradingform_rubric'), null, $options); $form->setType('description_editor', PARAM_RAW); diff --git a/grade/grading/form/rubric/js/rubriceditor.js b/grade/grading/form/rubric/js/rubriceditor.js index 107348c9b86..64da044c5f5 100644 --- a/grade/grading/form/rubric/js/rubriceditor.js +++ b/grade/grading/form/rubric/js/rubriceditor.js @@ -83,6 +83,7 @@ M.gradingform_rubriceditor.editmode = function(el, editmode) { } ta.get('parentNode').one('.plainvalue').setStyle('display', 'none') ta.setStyle('display', 'block').setStyle('width', width).setStyle('height', height) + ta.focus() } } diff --git a/grade/grading/form/rubric/lib.php b/grade/grading/form/rubric/lib.php index a12a55c63cf..bdcefc41059 100644 --- a/grade/grading/form/rubric/lib.php +++ b/grade/grading/form/rubric/lib.php @@ -60,19 +60,28 @@ class gradingform_rubric_controller extends gradingform_controller { * Saves the rubric definition into the database * * @see parent::update_definition() - * @param stdClass $newdefinition rubric definition data as coming from {@link self::postupdate_definition_data()} + * @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 */ public function update_definition(stdClass $newdefinition, $usermodified = null) { global $DB; // firstly update the common definition data in the {grading_definition} table + if ($this->definition === false) { + // if definition does not exist yet, create a blank one with only required fields set + // (we need id to save files embedded in description) + parent::update_definition((object)array('descriptionformat' => FORMAT_MOODLE), $usermodified); + parent::load_definition(); + } + $options = self::description_form_field_options($this->get_context()); + $newdefinition = file_postupdate_standard_editor($newdefinition, 'description', $options, $this->get_context(), + 'gradingform_rubric', 'definition_description', $this->definition->id); parent::update_definition($newdefinition, $usermodified); - // reload the definition from the database - $this->load_definition(); - $currentdefinition = $this->get_definition(); - // update current data + // reload the definition from the database + $currentdefinition = $this->get_definition(true); + + // update rubric data $haschanges = false; if (empty($newdefinition->rubric_criteria)) { $newcriteria = array(); @@ -299,21 +308,6 @@ class gradingform_rubric_controller extends gradingform_controller { return format_text($description, $this->definition->descriptionformat, $formatoptions); } - /** - * Converts the rubric definition data from the submitted form back to the form - * suitable for storing in database - */ - public function postupdate_definition_data($data) { - if (!$this->definition) { - return $data; - } - $options = self::description_form_field_options($this->get_context()); - $data = file_postupdate_standard_editor($data, 'description', $options, $this->get_context(), - 'gradingform_rubric', 'definition_description', $this->definition->id); - // TODO change filearea for embedded files in grading_definition.description - return $data; - } - public function is_form_available($foruserid = null) { return true; // TODO this is temporary for testing! @@ -373,10 +367,11 @@ class gradingform_rubric_controller extends gradingform_controller { * * @param moodle_page $page * @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 * @return string */ - public function render_grade($page, $itemid, $defaultcontent) { + 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); } @@ -484,7 +479,8 @@ class gradingform_rubric_instance extends gradingform_instance { /** * Calculates the grade to be pushed to the gradebook - * @return int the grade on 0-100 scale + * + * @return int the valid grade from $this->get_controller()->get_grade_range() */ public function get_grade() { global $DB, $USER; @@ -494,20 +490,28 @@ class gradingform_rubric_instance extends gradingform_instance { $maxscore = 0; foreach ($this->get_controller()->get_definition()->rubric_criteria as $id => $criterion) { $keys = array_keys($criterion['levels']); - // TODO array_reverse($keys) if levels are sorted DESC + sort($keys); $minscore += $criterion['levels'][$keys[0]]['score']; $maxscore += $criterion['levels'][$keys[sizeof($keys)-1]]['score']; } - if ($maxscore == 0) { + if ($maxscore <= $minscore) { return -1; } + $graderange = array_keys($this->get_controller()->get_grade_range()); + if (empty($graderange)) { + return -1; + } + sort($graderange); + $mingrade = $graderange[0]; + $maxgrade = $graderange[sizeof($graderange) - 1]; + $curscore = 0; foreach ($grade as $id => $levelid) { $curscore += $this->get_controller()->get_definition()->rubric_criteria[$id]['levels'][$levelid]['score']; } - return $curscore/$maxscore*100; // TODO mapping + return round(($curscore-$minscore)/($maxscore-$minscore)*($maxgrade-$mingrade), 0) + $mingrade; // TODO mapping } /** diff --git a/mod/assignment/lib.php b/mod/assignment/lib.php index 908ea30776f..0a30eb4464f 100644 --- a/mod/assignment/lib.php +++ b/mod/assignment/lib.php @@ -332,7 +332,8 @@ class assignment_base { echo ''; $grade_str = '
'. get_string("grade").': '.$grade->str_long_grade. '
'; if (!empty($submission) && $controller = get_grading_manager($this->context, 'mod_assignment', 'submission')->get_active_controller()) { - echo $controller->render_grade($PAGE, $submission->id, $grade_str); + $controller->set_grade_range(make_grades_menu($this->assignment->grade)); + echo $controller->render_grade($PAGE, $submission->id, $item, $grade_str); } else { echo $grade_str; } @@ -780,6 +781,23 @@ class assignment_base { } } + /** + * Checks if grading method allows quickgrade mode. At the moment it is hardcoded + * that advanced grading methods do not allow quickgrade. + * + * Assignment type plugins are not allowed to override this method + * + * @return boolean + */ + public final function quickgrade_mode_allowed() { + global $CFG; + require_once("$CFG->dirroot/grade/grading/lib.php"); + if ($controller = get_grading_manager($this->context, 'mod_assignment', 'submission')->get_active_controller()) { + return false; + } + return true; + } + /** * Helper method updating the listing on the main script from popup using javascript * @@ -794,7 +812,7 @@ class assignment_base { $perpage = get_user_preferences('assignment_perpage', 10); - $quickgrade = get_user_preferences('assignment_quickgrade', 0); + $quickgrade = get_user_preferences('assignment_quickgrade', 0) && $this->quickgrade_mode_allowed(); /// Run some Javascript to try and update the parent page $output .= '