Skip to content
Browse files

Merge pull request #13 from marinaglancy/wip-formvalidation-rubric

Initial prototype of integrating advanced grading methods into current forms

There is a new form element called 'grading', which receives grading_controller as an argument and uses it's functions to produce html and validate the value.

The biggest change in grading form is that I included call to new function validate_and_preprocess_feedback, which validates and also fills the xgrade field with value, calculated by controller

Another issue: when the teacher grades the student on offline assignment for the first time, there may be no entry in submission table (and therefore no id). So I create a submission if there is advanced grading otherwise we won't be able to save via AJAX the process of filling rubric, because normal grading will create an entry only on submit.

And as an example I created text field in rubric, that is saved as grade. There is validation that value can not be more than 100.
  • Loading branch information...
2 parents 6abcb0c + 6798c63 commit a5c4c99b24034db5eab416a7ff6a4fd50b29eaff @mudrd8mz mudrd8mz committed Oct 12, 2011
Showing with 287 additions and 7 deletions.
  1. +24 −0 grade/grading/form/lib.php
  2. +57 −0 grade/grading/form/rubric/lib.php
  3. +13 −0 grade/grading/lib.php
  4. +1 −0 lang/en/grading.php
  5. +118 −0 lib/form/grading.php
  6. +1 −0 lib/formslib.php
  7. +73 −7 mod/assignment/lib.php
View
24 grade/grading/form/lib.php
@@ -264,6 +264,30 @@ public function prepare_instance($raterid, $itemid) {
}
}
+ /**
+ * Saves non-js data and returns the gradebook grade
+ */
+ abstract public function save_and_get_grade($itemid, $formdata);
+
+ /**
+ * Returns html for form element
+ */
+ abstract public function to_html($gradingformelement);
+
+ /**
+ *
+ */
+ public function default_validation_error_message() {
+ return '';
+ }
+
+ /**
+ *
+ */
+ public function validate_grading_element($elementvalue, $itemid) {
+ return true;
+ }
+
////////////////////////////////////////////////////////////////////////////
View
57 grade/grading/form/rubric/lib.php
@@ -226,6 +226,41 @@ public function get_definition_for_editing() {
return $properties;
}
+ /**
+ * Saves non-js data and returns the gradebook grade
+ */
+ public function save_and_get_grade($itemid, $formdata) {
+ // TODO: this function is a patch at the moment!
+ if (is_array($formdata) && array_key_exists('grade', $formdata)) {
+ return $formdata['grade'];
+ }
+ return -1;
+ }
+
+ /**
+ * Returns html for form element
+ */
+ public function to_html($gradingformelement) {
+ // TODO: this function is a patch at the moment!
+
+ //global $PAGE, $USER;
+ //$gradingrenderer = $this->prepare_renderer($PAGE);
+ $output = '';
+ $elementname = $gradingformelement->getName();
+ $elementvalue = $gradingformelement->getValue();
+ $submissionid = $gradingformelement->get_grading_attribute('submissionid');
+ $output .= "assessing submission $submissionid<br />";
+ $output .= html_writer::empty_tag('input', array('type' => 'text', 'name' => $elementname.'[grade]', 'size' => '20', 'value' => $elementvalue['grade']));
+ //$output .= "assessing user $userid on assignment $assignmentid<br>";
+ //TODO find $submissionid from $userid & $assignmentid (may not exist yet, actually)
+ /*$submissionid = null;
+ $gradingwidget = $this->make_grading_widget($USER->id, $submissionid);
+ if ($gradingwidget instanceof renderable) {
+ return $output. $gradingrenderer->render($gradingwidget);
+ }*/
+ return $output;
+ }
+
// TODO the following functions may be moved to parent:
/**
@@ -273,4 +308,26 @@ public function postupdate_definition_data($data) {
// 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!
+ }
+
+ /**
+ *
+ */
+ public function default_validation_error_message() {
+ return 'Validation failed';
+ }
+
+ /**
+ *
+ */
+ public function validate_grading_element($elementvalue, $itemid) {
+ if ($elementvalue['grade'] > 100 || $elementvalue['grade'] < 0) {
+ return false;
+ }
+ return true;
+ }
}
View
13 grade/grading/lib.php
@@ -374,6 +374,19 @@ public function get_controller($method) {
return new $classname($this->context, $this->component, $this->area, $this->areacache->id);
}
+ /**
+ * Returns the controller for the active method if it is available
+ */
+ public function get_active_controller() {
+ if ($gradingmethod = $this->get_active_method()) {
+ $controller = $this->get_controller($gradingmethod);
+ if ($controller->is_form_available()) {
+ return $controller;
+ }
+ }
+ return null;
+ }
+
////////////////////////////////////////////////////////////////////////////
/**
View
1 lang/en/grading.php
@@ -26,6 +26,7 @@
defined('MOODLE_INTERNAL') || die();
+$string['exc_gradingformelement'] = 'Unable to instantiate grading form element';
$string['formnotavailable'] = 'Advanced grading method was selected to use but the grading form is not available yet. You may need to define it first via a link in the Settings block.';
$string['gradinginarea'] = 'Grading ({$a})';
$string['gradingmethod'] = 'Grading method';
View
118 lib/form/grading.php
@@ -0,0 +1,118 @@
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Element-container for advanced grading custom input
+ *
+ * @copyright 2011 Marina Glancy
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+global $CFG;
+require_once("HTML/QuickForm/element.php");
+require_once($CFG->dirroot.'/grade/grading/form/lib.php');
+
+if (class_exists('HTML_QuickForm')) {
+ HTML_QuickForm::registerRule('gradingvalidated', 'callback', '_validate', 'MoodleQuickForm_grading');
+}
+
+/**
+ * HTML class for a grading element
+ *
+ * @author Marina Glancy
+ * @access public
+ */
+class MoodleQuickForm_grading extends HTML_QuickForm_input{
+ /**
+ * html for help button, if empty then no help
+ *
+ * @var string
+ */
+ var $_helpbutton='';
+
+ private $gradingattributes;
+
+ function MoodleQuickForm_grading($elementName=null, $elementLabel=null, $attributes=null) {
+ parent::HTML_QuickForm_input($elementName, $elementLabel, $attributes);
+ $this->gradingattributes = $attributes;
+ }
+
+ function toHtml(){
+ return $this->get_controller()->to_html($this);
+ }
+
+ function get_grading_attribute($name) {
+ return $this->gradingattributes[$name];
+ }
+
+ function get_controller() {
+ return $this->get_grading_attribute('controller');
+ }
+
+ /**
+ * set html for help button
+ *
+ * @access public
+ * @param array $help array of arguments to make a help button
+ * @param string $function function name to call to get html
+ */
+ function setHelpButton($helpbuttonargs, $function='helpbutton'){
+ debugging('component setHelpButton() is not used any more, please use $mform->setHelpButton() instead');
+ }
+
+ /**
+ * get html for help button
+ *
+ * @access public
+ * @return string html for help button
+ */
+ function getHelpButton(){
+ return $this->_helpbutton;
+ }
+
+ /**
+ * @return string
+ */
+ function getElementTemplateType(){
+ return 'default';
+ }
+
+ /**
+ * Adds necessary rules to the element
+ */
+ function onQuickFormEvent($event, $arg, &$caller) {
+ if ($event == 'createElement') {
+ $attributes = $arg[2];
+ if (!is_array($attributes) || !array_key_exists('controller', $attributes) || !($attributes['controller'] instanceof gradingform_controller)) {
+ throw new moodle_exception('exc_gradingformelement', 'grading');
+ }
+ }
+
+ $name = $this->getName();
+ if ($name && $caller->elementExists($name)) {
+ $caller->addRule($name, $this->get_controller()->default_validation_error_message(), 'gradingvalidated', $this->gradingattributes);
+ }
+ return parent::onQuickFormEvent($event, $arg, $caller);
+ }
+
+ /**
+ * Function registered as rule for this element and is called when this element is being validated
+ */
+ static function _validate($elementValue, $attributes = null) {
+ return $attributes['controller']->validate_grading_element($elementValue, $attributes['submissionid']);
+ }
+}
View
1 lib/formslib.php
@@ -2487,6 +2487,7 @@ function getValidationScript($format = null) {
MoodleQuickForm::registerElementType('filemanager', "$CFG->libdir/form/filemanager.php", 'MoodleQuickForm_filemanager');
MoodleQuickForm::registerElementType('filepicker', "$CFG->libdir/form/filepicker.php", 'MoodleQuickForm_filepicker');
MoodleQuickForm::registerElementType('format', "$CFG->libdir/form/format.php", 'MoodleQuickForm_format');
+MoodleQuickForm::registerElementType('grading', "$CFG->libdir/form/grading.php", 'MoodleQuickForm_grading');
MoodleQuickForm::registerElementType('group', "$CFG->libdir/form/group.php", 'MoodleQuickForm_group');
MoodleQuickForm::registerElementType('header', "$CFG->libdir/form/header.php", 'MoodleQuickForm_header');
MoodleQuickForm::registerElementType('hidden', "$CFG->libdir/form/hidden.php", 'MoodleQuickForm_hidden');
View
80 mod/assignment/lib.php
@@ -630,7 +630,10 @@ function submissions($mode) {
switch ($mode) {
case 'grade': // We are in a main window grading
- if ($submission = $this->process_feedback()) {
+ if (!$this->validate_and_preprocess_feedback()) {
+ // validation failed
+ $this->display_submission();
+ } else if ($submission = $this->process_feedback()) {
$this->display_submissions(get_string('changessaved'));
} else {
$this->display_submissions();
@@ -744,7 +747,11 @@ function submissions($mode) {
case 'saveandnext':
///We are in pop up. save the current one and go to the next one.
//first we save the current changes
- if ($submission = $this->process_feedback()) {
+ if (!$this->validate_and_preprocess_feedback()) {
+ // validation failed
+ $this->display_submission();
+ break;
+ } else if ($submission = $this->process_feedback()) {
//print_heading(get_string('changessaved'));
//$extra_javascript = $this->update_main_listing($submission);
}
@@ -1039,7 +1046,7 @@ function display_submission($offset=-1,$userid =-1, $display=true) {
} elseif ($assignment->assignmenttype == 'uploadsingle') {
$mformdata->fileui_options = array('subdirs'=>0, 'maxbytes'=>$CFG->userquota, 'maxfiles'=>1, 'accepted_types'=>'*', 'return_types'=>FILE_INTERNAL);
}
- $gradingman = get_grading_manager($this->context, 'mod_assignment', 'submission');
+ /*$gradingman = get_grading_manager($this->context, 'mod_assignment', 'submission');
if ($gradingmethod = $gradingman->get_active_method()) {
$controller = $gradingman->get_controller($gradingmethod);
if ($controller->is_form_available()) {
@@ -1067,14 +1074,23 @@ function display_submission($offset=-1,$userid =-1, $display=true) {
} else {
notice(get_string('formnotavailable', 'core_grading'), new moodle_url('/course/view.php', array('id' => $assignment->course)));
}
+ }*/
+ if ($controller = get_grading_manager($this->context, 'mod_assignment', 'submission')->get_active_controller()) {
+ if (!isset($submission->id)) {
+ // TODO this is a patch if submission id does not exist yet
+ $mformdata->submission = $this->get_submission($user->id, true);
+ }
+ $mformdata->advancedgradingcontroller = $controller;
}
$submitform = new mod_assignment_grading_form( null, $mformdata );
if (!$display) {
$ret_data = new stdClass();
$ret_data->mform = $submitform;
- $ret_data->fileui_options = $mformdata->fileui_options;
+ if (isset($mformdata->fileui_options)) {
+ $ret_data->fileui_options = $mformdata->fileui_options;
+ }
return $ret_data;
}
@@ -1575,6 +1591,33 @@ function display_submissions($message='') {
}
/**
+ * Validates the submitted form and returns false if validation did not pass.
+ * If validation passes, preprocess advanced grading (if applicable) and returns true.
+ */
+ function validate_and_preprocess_feedback() {
+ if (!$feedback = data_submitted()) {
+ return true; // No incoming data, nothing to validate
+ }
+ $userid = required_param('userid', PARAM_INT);
+ $offset = required_param('offset', PARAM_INT);
+ $submissiondata = $this->display_submission($offset, $userid, false);
+ $mform = $submissiondata->mform;
+ if ($mform->is_submitted()) {
+ if (!$mform->is_validated()) {
+ return false;
+ }
+ // preprocess advanced grading here
+ if ($controller = $mform->use_advanced_grading()) {
+ $data = $mform->get_data();
+ // TODO find better way to find submission id
+ $submission = $this->get_submission($userid);
+ $_POST['xgrade'] = $controller->save_and_get_grade($submission->id, $data->advancedgrading);
+ }
+ }
+ return true;
+ }
+
+ /**
* Process teacher feedback submission
*
* This is called by submissions() when a grading even has taken place.
@@ -2252,6 +2295,10 @@ function definition() {
global $OUTPUT;
$mform =& $this->_form;
+ if (isset($this->_customdata->advancedgradingcontroller)) {
+ $this->use_advanced_grading($this->_customdata->advancedgradingcontroller);
+ }
+
$formattr = $mform->getAttributes();
$formattr['id'] = 'submitform';
$mform->setAttributes($formattr);
@@ -2297,6 +2344,19 @@ function definition() {
}
+ private $_advancegradingcontroller;
+ /**
+ * Gets or sets the controller for advanced grading
+ *
+ * @param <type> $controller
+ */
+ public function use_advanced_grading($controller = false) {
+ if ($controller !== false) {
+ $this->_advancegradingcontroller = $controller;
+ }
+ return $this->_advancegradingcontroller;
+ }
+
function add_grades_section() {
global $CFG;
$mform =& $this->_form;
@@ -2307,9 +2367,10 @@ function add_grades_section() {
$mform->addElement('header', 'Grades', get_string('grades', 'grades'));
- if (!empty($this->_customdata->advancedgradingenabled)) {
- $mform->addElement('static', 'advancedgradingwidget', get_string('grade').':', $this->_customdata->advancedgradingwidget);
-
+ if ($controller = $this->use_advanced_grading()) {
+ // TODO what if submission id does not exist yet!
+ $mform->addElement('grading', 'advancedgrading', get_string('grade').':',
+ array('controller' => $controller, 'submissionid' => $this->_customdata->submission->id));
} else {
// use simple direct grading
$grademenu = make_grades_menu($this->_customdata->assignment->grade);
@@ -2468,6 +2529,11 @@ public function get_data() {
}
$data = file_postupdate_standard_editor($data, 'submissioncomment', $editoroptions, $this->_customdata->context, $editoroptions['component'], $editoroptions['filearea'], $itemid);
}
+
+ if ($this->use_advanced_grading() && !isset($data->advancedgrading)) {
+ $data->advancedgrading = null;
+ }
+
return $data;
}
}

0 comments on commit a5c4c99

Please sign in to comment.
Something went wrong with that request. Please try again.