diff --git a/grade/grading/form/lib.php b/grade/grading/form/lib.php index aa076c9aab8..ba14e8002d0 100644 --- a/grade/grading/form/lib.php +++ b/grade/grading/form/lib.php @@ -264,6 +264,30 @@ abstract class gradingform_controller { } } + /** + * 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; + } + //////////////////////////////////////////////////////////////////////////// diff --git a/grade/grading/form/rubric/lib.php b/grade/grading/form/rubric/lib.php index f34bad57543..fd79691f57f 100644 --- a/grade/grading/form/rubric/lib.php +++ b/grade/grading/form/rubric/lib.php @@ -226,6 +226,41 @@ class gradingform_rubric_controller extends gradingform_controller { 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
"; + $output .= html_writer::empty_tag('input', array('type' => 'text', 'name' => $elementname.'[grade]', 'size' => '20', 'value' => $elementvalue['grade'])); + //$output .= "assessing user $userid on assignment $assignmentid
"; + //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 @@ class gradingform_rubric_controller extends gradingform_controller { // 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; + } } diff --git a/grade/grading/lib.php b/grade/grading/lib.php index 7a354d5b8e3..aed7f8530d7 100644 --- a/grade/grading/lib.php +++ b/grade/grading/lib.php @@ -374,6 +374,19 @@ class grading_manager { 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; + } + //////////////////////////////////////////////////////////////////////////// /** diff --git a/lang/en/grading.php b/lang/en/grading.php index 27ac999af00..5646d4773b3 100644 --- a/lang/en/grading.php +++ b/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'; diff --git a/lib/form/grading.php b/lib/form/grading.php new file mode 100644 index 00000000000..ef11df553b1 --- /dev/null +++ b/lib/form/grading.php @@ -0,0 +1,118 @@ +. + +/** + * 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']); + } +} diff --git a/lib/formslib.php b/lib/formslib.php index 45e01a2092e..f02469e91b8 100644 --- a/lib/formslib.php +++ b/lib/formslib.php @@ -2487,6 +2487,7 @@ MoodleQuickForm::registerElementType('file', "$CFG->libdir/form/file.php", 'Mood 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'); diff --git a/mod/assignment/lib.php b/mod/assignment/lib.php index 59ac6175751..987f5b8eeb4 100644 --- a/mod/assignment/lib.php +++ b/mod/assignment/lib.php @@ -630,7 +630,10 @@ class assignment_base { 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 @@ class assignment_base { 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 @@ class assignment_base { } 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,6 +1074,13 @@ class assignment_base { } 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 ); @@ -1074,7 +1088,9 @@ class assignment_base { 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; } @@ -1574,6 +1590,33 @@ class assignment_base { echo $OUTPUT->footer(); } + /** + * 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 * @@ -2252,6 +2295,10 @@ class mod_assignment_grading_form extends moodleform { 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 @@ class mod_assignment_grading_form extends moodleform { } + private $_advancegradingcontroller; + /** + * Gets or sets the controller for advanced grading + * + * @param $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 @@ class mod_assignment_grading_form extends moodleform { $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 @@ class mod_assignment_grading_form extends moodleform { } $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; } }