/** * Perform minimal validation on the grade form * @param array $data * @param array $files */ function validation($data, $files) { global $DB; $errors = parent::validation($data, $files); // advanced grading if (!array_key_exists('grade', $data)) { return $errors; } if ($this->assignment->get_instance()->grade > 0) { if (unformat_float($data['grade']) === null && (!empty($data['grade']))) { $errors['grade'] = get_string('invalidfloatforgrade', 'assign', $data['grade']); } else if (unformat_float($data['grade']) > $this->assignment->get_instance()->grade) { $errors['grade'] = get_string('gradeabovemaximum', 'assign', $this->assignment->get_instance()->grade); } else if (unformat_float($data['grade']) < 0) { $errors['grade'] = get_string('gradebelowzero', 'assign'); } } else { // this is a scale if ($scale = $DB->get_record('scale', array('id'=>-($this->assignment->get_instance()->grade)))) { $scaleoptions = make_menu_from_list($scale->scale); if (!array_key_exists((int)$data['grade'], $scaleoptions)) { $errors['grade'] = get_string('invalidgradeforscale', 'assign'); } } } return $errors; }
/** * Update the criteria information stored in the database * * @param stdClass $data Form data */ public function update_config(&$data) { if (!empty($data->criteria_grade)) { $formatedgrade = unformat_float($data->criteria_grade_value); // TODO validation if (!empty($formatedgrade) && is_numeric($formatedgrade)) { $this->course = $data->id; $this->gradepass = $formatedgrade; $this->insert(); } } }
public function get_data() { if (!($item = parent::get_data())) { return false; } $num1 = unformat_float($item->rangefrom, true); if ($num1 === false || $num1 === null) { $num1 = '-'; } $num2 = unformat_float($item->rangeto, true); if ($num2 === false || $num2 === null) { $num2 = '-'; } if ($num1 === '-' or $num2 === '-') { $item->presentation = $num1 . '|' . $num2; return $item; } if ($num1 > $num2) { $item->presentation = $num2 . '|' . $num1; } else { $item->presentation = $num1 . '|' . $num2; } return $item; }
$numpages = count($pagebreakpositions); // Ensure the target page number is in range. for ($i = $moveselectedonpage; $i > $numpages; $i--) { $questions[] = 0; $pagebreakpositions[] = count($questions) - 1; } $moveselectedpos = $pagebreakpositions[$moveselectedonpage - 1]; // Do the move. array_splice($questions, $moveselectedpos, 0, $selectedquestionids); $quiz->questions = implode(',', $questions); // Update the database. $DB->set_field('quiz', 'questions', $quiz->questions, array('id' => $quiz->id)); $deletepreviews = true; } // If rescaling is required save the new maximum. $maxgrade = unformat_float(optional_param('maxgrade', -1, PARAM_RAW)); if ($maxgrade >= 0) { quiz_set_grade($maxgrade, $quiz); } if ($deletepreviews) { quiz_delete_previews($quiz); } if ($recomputesummarks) { quiz_update_sumgrades($quiz); quiz_update_all_attempt_sumgrades($quiz); quiz_update_all_final_grades($quiz); quiz_update_grades($quiz, 0, true); } redirect($afteractionurl); } $questionbank->process_actions($thispageurl, $cm);
/** * Test localised float unformatting. */ public function test_unformat_float() { // Tests without the localised decimal separator. // Special case for null, empty or white spaces only strings. $this->assertEquals(null, unformat_float(null)); $this->assertEquals(null, unformat_float('')); $this->assertEquals(null, unformat_float(' ')); // Regular use. $this->assertEquals(5.4, unformat_float('5.4')); $this->assertEquals(5.4, unformat_float('5.4', true)); // No decimal. $this->assertEquals(5.0, unformat_float('5')); // Custom number of decimal. $this->assertEquals(5.43267, unformat_float('5.43267')); // Empty decimal. $this->assertEquals(100.0, unformat_float('100.00')); // With the thousand separator. $this->assertEquals(1000.0, unformat_float('1 000')); $this->assertEquals(1000.32, unformat_float('1 000.32')); // Negative number. $this->assertEquals(-100.0, unformat_float('-100')); // Wrong value. $this->assertEquals(0.0, unformat_float('Wrong value')); // Wrong value in strict mode. $this->assertFalse(unformat_float('Wrong value', true)); // Combining options. $this->assertEquals(-1023.862567, unformat_float(' -1 023.862567 ')); // Bad decimal separator (should crop the decimal). $this->assertEquals(50.0, unformat_float('50,57')); // Bad decimal separator in strict mode (should return false). $this->assertFalse(unformat_float('50,57', true)); // Tests with a localised decimal separator. $this->define_local_decimal_separator(); // We repeat the tests above but with the current decimal separator. // Regular use without and with the localised separator. $this->assertEquals(5.4, unformat_float('5.4')); $this->assertEquals(5.4, unformat_float('5X4')); // Custom number of decimal. $this->assertEquals(5.43267, unformat_float('5X43267')); // Empty decimal. $this->assertEquals(100.0, unformat_float('100X00')); // With the thousand separator. $this->assertEquals(1000.32, unformat_float('1 000X32')); // Bad different separator (should crop the decimal). $this->assertEquals(50.0, unformat_float('50Y57')); // Bad different separator in strict mode (should return false). $this->assertFalse(unformat_float('50Y57', true)); // Combining options. $this->assertEquals(-1023.862567, unformat_float(' -1 023X862567 ')); // Combining options in strict mode. $this->assertEquals(-1023.862567, unformat_float(' -1 023X862567 ', true)); }
} $grade_item->outcomeid = null; // update hiding flag if ($hiddenuntil) { $grade_item->set_hidden($hiddenuntil, false); } else { $grade_item->set_hidden($hidden, false); } $grade_item->set_locktime($locktime); // locktime first - it might be removed when unlocking $grade_item->set_locked($locked, false, true); $grade_item->update(); // We don't need to insert it, it's already created when the category is created // set parent if needed if (isset($data->parentcategory)) { $grade_category->set_parent($data->parentcategory, 'gradebook'); } // update agg coef if needed if (isset($data->aggregationcoef)) { $data->aggregationcoef = unformat_float($data->aggregationcoef); $grade_item = $grade_category->load_grade_item(); $grade_item->aggregationcoef = $data->aggregationcoef; $grade_item->update(); } redirect($returnurl); } } print_grade_page_head($courseid, 'edittree', null, $heading); $mform->display(); print_footer($course); die;
echo "<br/>grade is {$value}"; $status = false; import_cleanup($importcode); echo $OUTPUT->notification(get_string('badgrade', 'grades')); break 3; } $value = $key; } $newgrade->finalgrade = $value; } else { if ($value === '' or $value == '-') { $value = null; // No grade. } else { // If the value has a local decimal or can correctly be unformatted, do it. $validvalue = unformat_float($value, true); if ($validvalue !== false) { $value = $validvalue; } else { // Non numeric grade value supplied, possibly mapped wrong column. echo "<br/>t0 is {$t0}"; echo "<br/>grade is {$value}"; $status = false; import_cleanup($importcode); echo $OUTPUT->notification(get_string('badgrade', 'grades')); break 3; } } $newgrade->finalgrade = $value; } $newgrades[] = $newgrade;
/** * Apply a grade from a grading form to a user (may be called multiple times for a group submission) * * @param stdClass $formdata - the data from the form * @param int $userid - the user to apply the grade to * @return void */ private function apply_grade_to_user($formdata, $userid) { global $USER, $CFG, $DB; $grade = $this->get_user_grade($userid, true); $gradingdisabled = $this->grading_disabled($userid); $gradinginstance = $this->get_grading_instance($userid, $gradingdisabled); if (!$gradingdisabled) { if ($gradinginstance) { $grade->grade = $gradinginstance->submit_and_get_grade($formdata->advancedgrading, $grade->id); } else { // Handle the case when grade is set to No Grade. if (isset($formdata->grade)) { $grade->grade= grade_floatval(unformat_float($formdata->grade)); } } } $grade->grader= $USER->id; $adminconfig = $this->get_admin_config(); $gradebookplugin = $adminconfig->feedback_plugin_for_gradebook; // Call save in plugins. foreach ($this->feedbackplugins as $plugin) { if ($plugin->is_enabled() && $plugin->is_visible()) { if (!$plugin->save($grade, $formdata)) { $result = false; print_error($plugin->get_error()); } if (('assignfeedback_' . $plugin->get_type()) == $gradebookplugin) { // This is the feedback plugin chose to push comments to the gradebook. $grade->feedbacktext = $plugin->text_for_gradebook($grade); $grade->feedbackformat = $plugin->format_for_gradebook($grade); } } } $this->update_grade($grade); $user = $DB->get_record('user', array('id' => $userid), '*', MUST_EXIST); $this->add_to_log('grade submission', $this->format_grade_for_log($grade)); }
/** * Validates the form input * * @param array $data submitted data * @param array $files submitted files * @return array eventual errors indexed by the field name */ public function validation($data, $files) { $errors = parent::validation($data, $files); // Validate lists of allowed extensions. foreach (array('submissionfiletypes', 'overallfeedbackfiletypes') as $fieldname) { if (isset($data[$fieldname])) { $invalidextensions = workshop::invalid_file_extensions($data[$fieldname], array_keys(core_filetypes::get_types())); if ($invalidextensions) { $errors[$fieldname] = get_string('err_unknownfileextension', 'mod_workshop', workshop::clean_file_extensions($invalidextensions)); } } } // check the phases borders are valid if ($data['submissionstart'] > 0 and $data['submissionend'] > 0 and $data['submissionstart'] >= $data['submissionend']) { $errors['submissionend'] = get_string('submissionendbeforestart', 'mod_workshop'); } if ($data['assessmentstart'] > 0 and $data['assessmentend'] > 0 and $data['assessmentstart'] >= $data['assessmentend']) { $errors['assessmentend'] = get_string('assessmentendbeforestart', 'mod_workshop'); } // check the phases do not overlap if (max($data['submissionstart'], $data['submissionend']) > 0 and max($data['assessmentstart'], $data['assessmentend']) > 0) { $phasesubmissionend = max($data['submissionstart'], $data['submissionend']); $phaseassessmentstart = min($data['assessmentstart'], $data['assessmentend']); if ($phaseassessmentstart == 0) { $phaseassessmentstart = max($data['assessmentstart'], $data['assessmentend']); } if ($phasesubmissionend > 0 and $phaseassessmentstart > 0 and $phaseassessmentstart < $phasesubmissionend) { foreach (array('submissionend', 'submissionstart', 'assessmentstart', 'assessmentend') as $f) { if ($data[$f] > 0) { $errors[$f] = get_string('phasesoverlap', 'mod_workshop'); break; } } } } // Check that the submission grade pass is a valid number. if (!empty($data['submissiongradepass'])) { $submissiongradefloat = unformat_float($data['submissiongradepass'], true); if ($submissiongradefloat === false) { $errors['submissiongradepass'] = get_string('err_numeric', 'form'); } else { if ($submissiongradefloat > $data['grade']) { $errors['submissiongradepass'] = get_string('gradepassgreaterthangrade', 'grades', $data['grade']); } } } // Check that the grade pass is a valid number. if (!empty($data['gradinggradepass'])) { $gradepassfloat = unformat_float($data['gradinggradepass'], true); if ($gradepassfloat === false) { $errors['gradinggradepass'] = get_string('err_numeric', 'form'); } else { if ($gradepassfloat > $data['gradinggrade']) { $errors['gradinggradepass'] = get_string('gradepassgreaterthangrade', 'grades', $data['gradinggrade']); } } } return $errors; }
/** * Apply a grade from a grading form to a user (may be called multiple times for a group submission). * * @param stdClass $formdata - the data from the form * @param int $userid - the user to apply the grade to * @param int attemptnumber - The attempt number to apply the grade to. * @return void */ protected function apply_grade_to_user($formdata, $userid, $attemptnumber) { global $USER, $CFG, $DB; $grade = $this->get_user_grade($userid, true, $attemptnumber); $gradingdisabled = $this->grading_disabled($userid); $gradinginstance = $this->get_grading_instance($userid, $grade, $gradingdisabled); if (!$gradingdisabled) { if ($gradinginstance) { $grade->grade = $gradinginstance->submit_and_get_grade($formdata->advancedgrading, $grade->id); } else { // Handle the case when grade is set to No Grade. if (isset($formdata->grade)) { $grade->grade = grade_floatval(unformat_float($formdata->grade)); } } } $grade->grader= $USER->id; $adminconfig = $this->get_admin_config(); $gradebookplugin = $adminconfig->feedback_plugin_for_gradebook; // Call save in plugins. foreach ($this->feedbackplugins as $plugin) { if ($plugin->is_enabled() && $plugin->is_visible()) { if (!$plugin->save($grade, $formdata)) { $result = false; print_error($plugin->get_error()); } if (('assignfeedback_' . $plugin->get_type()) == $gradebookplugin) { // This is the feedback plugin chose to push comments to the gradebook. $grade->feedbacktext = $plugin->text_for_gradebook($grade); $grade->feedbackformat = $plugin->format_for_gradebook($grade); } } } $this->update_grade($grade); // Note the default if not provided for this option is true (e.g. webservices). // This is for backwards compatibility. if (!isset($formdata->sendstudentnotifications) || $formdata->sendstudentnotifications) { $this->notify_grade_modified($grade); } $this->add_to_log('grade submission', $this->format_grade_for_log($grade)); }
function validation($data, $files) { global $COURSE, $DB; $errors = parent::validation($data, $files); $mform =& $this->_form; $errors = array(); if ($mform->elementExists('name')) { $name = trim($data['name']); if ($name == '') { $errors['name'] = get_string('required'); } } $grade_item = grade_item::fetch(array('itemtype'=>'mod', 'itemmodule'=>$data['modulename'], 'iteminstance'=>$data['instance'], 'itemnumber'=>0, 'courseid'=>$COURSE->id)); if ($data['coursemodule']) { $cm = $DB->get_record('course_modules', array('id'=>$data['coursemodule'])); } else { $cm = null; } if ($mform->elementExists('cmidnumber')) { // verify the idnumber if (!grade_verify_idnumber($data['cmidnumber'], $COURSE->id, $grade_item, $cm)) { $errors['cmidnumber'] = get_string('idnumbertaken'); } } // Completion: Don't let them choose automatic completion without turning // on some conditions. Ignore this check when completion settings are // locked, as the options are then disabled. if (array_key_exists('completion', $data) && $data['completion'] == COMPLETION_TRACKING_AUTOMATIC && !empty($data['completionunlocked'])) { if (empty($data['completionview']) && empty($data['completionusegrade']) && !$this->completion_rule_enabled($data)) { $errors['completion'] = get_string('badautocompletion', 'completion'); } } // Conditions: Don't let them set dates which make no sense if (array_key_exists('availablefrom', $data) && $data['availablefrom'] && $data['availableuntil'] && $data['availablefrom'] >= $data['availableuntil']) { $errors['availablefrom'] = get_string('badavailabledates', 'condition'); } // Conditions: Verify that the grade conditions are numbers, and make sense. if (array_key_exists('conditiongradegroup', $data)) { foreach ($data['conditiongradegroup'] as $i => $gradedata) { if ($gradedata['conditiongrademin'] !== '' && !is_numeric(unformat_float($gradedata['conditiongrademin']))) { $errors["conditiongradegroup[{$i}]"] = get_string('gradesmustbenumeric', 'condition'); continue; } if ($gradedata['conditiongrademax'] !== '' && !is_numeric(unformat_float($gradedata['conditiongrademax']))) { $errors["conditiongradegroup[{$i}]"] = get_string('gradesmustbenumeric', 'condition'); continue; } if ($gradedata['conditiongrademin'] !== '' && $gradedata['conditiongrademax'] !== '' && unformat_float($gradedata['conditiongrademax']) <= unformat_float($gradedata['conditiongrademin'])) { $errors["conditiongradegroup[{$i}]"] = get_string('badgradelimits', 'condition'); continue; } if ($gradedata['conditiongrademin'] === '' && $gradedata['conditiongrademax'] === '' && $gradedata['conditiongradeitemid']) { $errors["conditiongradegroup[{$i}]"] = get_string('gradeitembutnolimits', 'condition'); continue; } if (($gradedata['conditiongrademin'] !== '' || $gradedata['conditiongrademax'] !== '') && !$gradedata['conditiongradeitemid']) { $errors["conditiongradegroup[{$i}]"] = get_string('gradelimitsbutnoitem', 'condition'); continue; } } } return $errors; }
public function validation($data, $files) { $errors = parent::validation($data, $files); // Conditions: Don't let them set dates which make no sense if (array_key_exists('availablefrom', $data) && $data['availablefrom'] && $data['availableuntil'] && $data['availablefrom'] >= $data['availableuntil']) { $errors['availablefrom'] = get_string('badavailabledates', 'condition'); } // Conditions: Verify that the grade conditions are numbers, and make sense. if (array_key_exists('conditiongradegroup', $data)) { foreach ($data['conditiongradegroup'] as $i => $gradedata) { if ($gradedata['conditiongrademin'] !== '' && !is_numeric(unformat_float($gradedata['conditiongrademin']))) { $errors["conditiongradegroup[{$i}]"] = get_string('gradesmustbenumeric', 'condition'); continue; } if ($gradedata['conditiongrademax'] !== '' && !is_numeric(unformat_float($gradedata['conditiongrademax']))) { $errors["conditiongradegroup[{$i}]"] = get_string('gradesmustbenumeric', 'condition'); continue; } if ($gradedata['conditiongrademin'] !== '' && $gradedata['conditiongrademax'] !== '' && unformat_float($gradedata['conditiongrademax']) <= unformat_float($gradedata['conditiongrademin'])) { $errors["conditiongradegroup[{$i}]"] = get_string('badgradelimits', 'condition'); continue; } if ($gradedata['conditiongrademin'] === '' && $gradedata['conditiongrademax'] === '' && $gradedata['conditiongradeitemid']) { $errors["conditiongradegroup[{$i}]"] = get_string('gradeitembutnolimits', 'condition'); continue; } if (($gradedata['conditiongrademin'] !== '' || $gradedata['conditiongrademax'] !== '') && !$gradedata['conditiongradeitemid']) { $errors["conditiongradegroup[{$i}]"] = get_string('gradelimitsbutnoitem', 'condition'); continue; } } } return $errors; }
/** * Utility function that resets grade/completion conditions in table based * in data from editing form. * * @param condition_info_base $ci Condition info * @param object $fromform Data from form * @param bool $wipefirst If true, wipes existing conditions */ protected static function update_from_form(condition_info_base $ci, $fromform, $wipefirst) { if ($wipefirst) { $ci->wipe_conditions(); } foreach ($fromform->conditiongradegroup as $record) { if ($record['conditiongradeitemid']) { $ci->add_grade_condition($record['conditiongradeitemid'], unformat_float($record['conditiongrademin']), unformat_float($record['conditiongrademax'])); } } foreach ($fromform->conditionfieldgroup as $record) { if ($record['conditionfield']) { $ci->add_user_field_condition($record['conditionfield'], $record['conditionfieldoperator'], $record['conditionfieldvalue']); } } if (isset($fromform->conditioncompletiongroup)) { foreach ($fromform->conditioncompletiongroup as $record) { if ($record['conditionsourcecmid']) { $ci->add_completion_condition($record['conditionsourcecmid'], $record['conditionrequiredcompletion']); } } } }
/** * Change the max mark for a slot. * * Saves changes to the question grades in the offlinequiz_group_questions table and any * corresponding question_attempts. * * @param \stdClass $slot row from the offlinequiz_group_questions table. * @param float $maxmark the new maxmark. * @return bool true if the new grade is different from the old one. */ public function update_slot_maxmark($slot, $maxmark) { global $DB; $maxmark = unformat_float($maxmark); if (abs($maxmark - $slot->maxmark) < 1.0E-7) { // Grade has not changed. Nothing to do. return false; } $trans = $DB->start_delegated_transaction(); $slot->maxmark = $maxmark; $DB->update_record('offlinequiz_group_questions', $slot); // We also need to update the maxmark for this question in other offlinequiz groups. $offlinequiz = $this->offlinequizobj->get_offlinequiz(); $currentgroupid = $offlinequiz->groupid; $groupids = $DB->get_fieldset_select('offlinequiz_groups', 'id', 'offlinequizid = :offlinequizid AND id <> :currentid', array('offlinequizid' => $offlinequiz->id, 'currentid' => $currentgroupid)); $params = array(); if ($groupids) { list($gsql, $params) = $DB->get_in_or_equal($groupids, SQL_PARAMS_NAMED, 'grp'); $sql = "SELECT *\n FROM {offlinequiz_group_questions}\n WHERE offlinequizid = :offlinequizid\n AND offlinegroupid {$gsql}\n AND questionid = :questionid "; $params['offlinequizid'] = $offlinequiz->id; $params['questionid'] = $slot->questionid; $otherslots = $DB->get_records_sql($sql, $params); foreach ($otherslots as $otherslot) { $otherslot->maxmark = $maxmark; $DB->update_record('offlinequiz_group_questions', $otherslot); } } // Now look at the maxmark of attemps. // We do this already in offlinequiz_update_question_instance. // \question_engine::set_max_mark_in_attempts(new \result_qubaids_for_offlinequiz($slot->offlinequizid, $slot->offlinegroupid), // $slot->slot, $maxmark); $trans->allow_commit(); return true; }
/** * Create this grade import form */ public function definition() { global $CFG, $PAGE, $DB; $mform = $this->_form; $params = $this->_customdata; $renderer = $PAGE->get_renderer('assign'); // Visible elements. $assignment = $params['assignment']; $csvdata = $params['csvdata']; $gradeimporter = $params['gradeimporter']; $update = false; $ignoremodified = $params['ignoremodified']; $draftid = $params['draftid']; if (!$gradeimporter) { print_error('invalidarguments'); return; } if ($csvdata) { $gradeimporter->parsecsv($csvdata); } $scaleoptions = null; if ($assignment->get_instance()->grade < 0) { if ($scale = $DB->get_record('scale', array('id' => -$assignment->get_instance()->grade))) { $scaleoptions = make_menu_from_list($scale->scale); } } if (!$gradeimporter->init()) { $thisurl = new moodle_url('/mod/assign/view.php', array('action' => 'viewpluginpage', 'pluginsubtype' => 'assignfeedback', 'plugin' => 'offline', 'pluginaction' => 'uploadgrades', 'id' => $assignment->get_course_module()->id)); print_error('invalidgradeimport', 'assignfeedback_offline', $thisurl); return; } $mform->addElement('header', 'importgrades', get_string('importgrades', 'assignfeedback_offline')); $updates = array(); while ($record = $gradeimporter->next()) { $user = $record->user; $grade = $record->grade; $modified = $record->modified; $userdesc = fullname($user); if ($assignment->is_blind_marking()) { $userdesc = get_string('hiddenuser', 'assign') . $assignment->get_uniqueid_for_user($user->id); } $usergrade = $assignment->get_user_grade($user->id, false); // Note: we lose the seconds when converting to user date format - so must not count seconds in comparision. $skip = false; $stalemodificationdate = $usergrade && $usergrade->timemodified > $modified + 60; if (!empty($scaleoptions)) { // This is a scale - we need to convert any grades to indexes in the scale. $scaleindex = array_search($grade, $scaleoptions); if ($scaleindex !== false) { $grade = $scaleindex; } else { $grade = ''; } } else { $grade = unformat_float($grade); } if ($usergrade && $usergrade->grade == $grade) { // Skip - grade not modified. $skip = true; } else { if (!isset($grade) || $grade === '' || $grade < 0) { // Skip - grade has no value. $skip = true; } else { if (!$ignoremodified && $stalemodificationdate) { // Skip - grade has been modified. $skip = true; } else { if ($assignment->grading_disabled($user->id)) { // Skip grade is locked. $skip = true; } else { if ($assignment->get_instance()->grade > -1 && ($grade < 0 || $grade > $assignment->get_instance()->grade)) { // Out of range. $skip = true; } } } } } if (!$skip) { $update = true; if (!empty($scaleoptions)) { $formattedgrade = $scaleoptions[$grade]; } else { $formattedgrade = format_float($grade, 2); } $updates[] = get_string('gradeupdate', 'assignfeedback_offline', array('grade' => $formattedgrade, 'student' => $userdesc)); } if ($ignoremodified || !$stalemodificationdate) { foreach ($record->feedback as $feedback) { $plugin = $feedback['plugin']; $field = $feedback['field']; $newvalue = $feedback['value']; $description = $feedback['description']; $oldvalue = ''; if ($usergrade) { $oldvalue = $plugin->get_editor_text($field, $usergrade->id); } if ($newvalue != $oldvalue) { $update = true; $updates[] = get_string('feedbackupdate', 'assignfeedback_offline', array('text' => $newvalue, 'field' => $description, 'student' => $userdesc)); } } } } $gradeimporter->close(false); if ($update) { $mform->addElement('html', $renderer->list_block_contents(array(), $updates)); } else { $mform->addElement('html', get_string('nochanges', 'assignfeedback_offline')); } $mform->addElement('hidden', 'id', $assignment->get_course_module()->id); $mform->setType('id', PARAM_INT); $mform->addElement('hidden', 'action', 'viewpluginpage'); $mform->setType('action', PARAM_ALPHA); $mform->addElement('hidden', 'confirm', 'true'); $mform->setType('confirm', PARAM_BOOL); $mform->addElement('hidden', 'plugin', 'offline'); $mform->setType('plugin', PARAM_PLUGIN); $mform->addElement('hidden', 'pluginsubtype', 'assignfeedback'); $mform->setType('pluginsubtype', PARAM_PLUGIN); $mform->addElement('hidden', 'pluginaction', 'uploadgrades'); $mform->setType('pluginaction', PARAM_ALPHA); $mform->addElement('hidden', 'importid', $gradeimporter->importid); $mform->setType('importid', PARAM_INT); $mform->addElement('hidden', 'encoding', $gradeimporter->get_encoding()); $mform->setType('encoding', PARAM_ALPHAEXT); $mform->addElement('hidden', 'separator', $gradeimporter->get_separator()); $mform->setType('separator', PARAM_ALPHA); $mform->addElement('hidden', 'ignoremodified', $ignoremodified); $mform->setType('ignoremodified', PARAM_BOOL); $mform->addElement('hidden', 'draftid', $draftid); $mform->setType('draftid', PARAM_INT); if ($update) { $this->add_action_buttons(true, get_string('confirm')); } else { $mform->addElement('cancel'); $mform->closeHeaderBefore('cancel'); } }
} if (!isset($data->grademin) || $data->grademin == '') { $data->grademin = 0; } $hidden = empty($data->hidden) ? 0 : $data->hidden; $hiddenuntil = empty($data->hiddenuntil) ? 0 : $data->hiddenuntil; unset($data->hidden); unset($data->hiddenuntil); $locked = empty($data->locked) ? 0 : $data->locked; $locktime = empty($data->locktime) ? 0 : $data->locktime; unset($data->locked); unset($data->locktime); $convert = array('grademax', 'grademin', 'gradepass', 'multfactor', 'plusfactor', 'aggregationcoef', 'aggregationcoef2'); foreach ($convert as $param) { if (property_exists($data, $param)) { $data->{$param} = unformat_float($data->{$param}); } } if (isset($data->aggregationcoef2) && $parent_category->aggregation == GRADE_AGGREGATE_SUM) { $data->aggregationcoef2 = $data->aggregationcoef2 / 100.0; } else { $data->aggregationcoef2 = $defaults['aggregationcoef2']; } $grade_item = new grade_item(array('id' => $id, 'courseid' => $courseid)); grade_item::set_properties($grade_item, $data); $grade_item->outcomeid = null; // Handle null decimals value if (!property_exists($data, 'decimals') or $data->decimals < 0) { $grade_item->decimals = null; } if (empty($grade_item->id)) {
/** * Given an object containing all the necessary data, * (defined by the form in mod_form.php) this function * will update an existing instance with new data. * * @param stdClass $workshop An object from the form in mod_form.php * @return bool success */ function workshop_update_instance(stdclass $workshop) { global $CFG, $DB; require_once(dirname(__FILE__) . '/locallib.php'); $workshop->timemodified = time(); $workshop->id = $workshop->instance; $workshop->useexamples = (int)!empty($workshop->useexamples); $workshop->usepeerassessment = 1; $workshop->useselfassessment = (int)!empty($workshop->useselfassessment); $workshop->latesubmissions = (int)!empty($workshop->latesubmissions); $workshop->phaseswitchassessment = (int)!empty($workshop->phaseswitchassessment); if (isset($workshop->gradinggradepass)) { $workshop->gradinggradepass = unformat_float($workshop->gradinggradepass); } if (isset($workshop->submissiongradepass)) { $workshop->submissiongradepass = unformat_float($workshop->submissiongradepass); } if (isset($workshop->submissionfiletypes)) { $workshop->submissionfiletypes = workshop::clean_file_extensions($workshop->submissionfiletypes); } if (isset($workshop->overallfeedbackfiletypes)) { $workshop->overallfeedbackfiletypes = workshop::clean_file_extensions($workshop->overallfeedbackfiletypes); } // todo - if the grading strategy is being changed, we may want to replace all aggregated peer grades with nulls $DB->update_record('workshop', $workshop); $context = context_module::instance($workshop->coursemodule); // process the custom wysiwyg editors if ($draftitemid = $workshop->instructauthorseditor['itemid']) { $workshop->instructauthors = file_save_draft_area_files($draftitemid, $context->id, 'mod_workshop', 'instructauthors', 0, workshop::instruction_editors_options($context), $workshop->instructauthorseditor['text']); $workshop->instructauthorsformat = $workshop->instructauthorseditor['format']; } if ($draftitemid = $workshop->instructreviewerseditor['itemid']) { $workshop->instructreviewers = file_save_draft_area_files($draftitemid, $context->id, 'mod_workshop', 'instructreviewers', 0, workshop::instruction_editors_options($context), $workshop->instructreviewerseditor['text']); $workshop->instructreviewersformat = $workshop->instructreviewerseditor['format']; } if ($draftitemid = $workshop->conclusioneditor['itemid']) { $workshop->conclusion = file_save_draft_area_files($draftitemid, $context->id, 'mod_workshop', 'conclusion', 0, workshop::instruction_editors_options($context), $workshop->conclusioneditor['text']); $workshop->conclusionformat = $workshop->conclusioneditor['format']; } // re-save the record with the replaced URLs in editor fields $DB->update_record('workshop', $workshop); // update gradebook items workshop_grade_item_update($workshop); workshop_grade_item_category_update($workshop); // update calendar events workshop_calendar_update($workshop, $workshop->coursemodule); return true; }
$mformclassname = 'mod_' . $module->name . '_mod_form'; $mform = new $mformclassname($data, $cw->section, $cm, $course); $mform->set_data($data); if ($mform->is_cancelled()) { if ($return && !empty($cm->id)) { redirect("{$CFG->wwwroot}/mod/{$module->name}/view.php?id={$cm->id}"); } else { redirect(course_get_url($course, $cw->section, array('sr' => $sectionreturn))); } } else { if ($fromform = $mform->get_data()) { // Convert the grade pass value - we may be using a language which uses commas, // rather than decimal points, in numbers. These need to be converted so that // they can be added to the DB. if (isset($fromform->gradepass)) { $fromform->gradepass = unformat_float($fromform->gradepass); } if (!empty($fromform->update)) { list($cm, $fromform) = update_moduleinfo($cm, $fromform, $course, $mform); } else { if (!empty($fromform->add)) { $fromform = add_moduleinfo($fromform, $course, $mform); } else { print_error('invaliddata'); } } if (isset($fromform->submitbutton)) { if (empty($fromform->showgradingmanagement)) { redirect("{$CFG->wwwroot}/mod/{$module->name}/view.php?id={$fromform->coursemodule}"); } else { $returnurl = new moodle_url("/mod/{$module->name}/view.php", array('id' => $fromform->coursemodule));
function validation($data, $files) { global $COURSE, $DB; $errors = parent::validation($data, $files); $mform =& $this->_form; $errors = array(); if ($mform->elementExists('name')) { $name = trim($data['name']); if ($name == '') { $errors['name'] = get_string('required'); } } $grade_item = grade_item::fetch(array('itemtype' => 'mod', 'itemmodule' => $data['modulename'], 'iteminstance' => $data['instance'], 'itemnumber' => 0, 'courseid' => $COURSE->id)); if ($data['coursemodule']) { $cm = $DB->get_record('course_modules', array('id' => $data['coursemodule'])); } else { $cm = null; } if ($mform->elementExists('cmidnumber')) { // verify the idnumber if (!grade_verify_idnumber($data['cmidnumber'], $COURSE->id, $grade_item, $cm)) { $errors['cmidnumber'] = get_string('idnumbertaken'); } } // Completion: Don't let them choose automatic completion without turning // on some conditions if (array_key_exists('completion', $data) && $data['completion'] == COMPLETION_TRACKING_AUTOMATIC) { if (empty($data['completionview']) && empty($data['completionusegrade']) && !$this->completion_rule_enabled($data)) { $errors['completion'] = get_string('badautocompletion', 'completion'); } } // Conditions: Don't let them set dates which make no sense if (array_key_exists('availablefrom', $data) && $data['availablefrom'] && $data['availableuntil'] && $data['availablefrom'] >= $data['availableuntil']) { $errors['availablefrom'] = get_string('badavailabledates', 'condition'); } // Conditions: Verify that the grade conditions are numbers, and make sense. if (array_key_exists('conditiongradegroup', $data)) { foreach ($data['conditiongradegroup'] as $i => $gradedata) { if ($gradedata['conditiongrademin'] !== '' && !is_numeric(unformat_float($gradedata['conditiongrademin']))) { $errors["conditiongradegroup[{$i}]"] = get_string('gradesmustbenumeric', 'condition'); continue; } if ($gradedata['conditiongrademax'] !== '' && !is_numeric(unformat_float($gradedata['conditiongrademax']))) { $errors["conditiongradegroup[{$i}]"] = get_string('gradesmustbenumeric', 'condition'); continue; } if ($gradedata['conditiongrademin'] !== '' && $gradedata['conditiongrademax'] !== '' && unformat_float($gradedata['conditiongrademax']) <= unformat_float($gradedata['conditiongrademin'])) { $errors["conditiongradegroup[{$i}]"] = get_string('badgradelimits', 'condition'); continue; } if ($gradedata['conditiongrademin'] === '' && $gradedata['conditiongrademax'] === '' && $gradedata['conditiongradeitemid']) { $errors["conditiongradegroup[{$i}]"] = get_string('gradeitembutnolimits', 'condition'); continue; } if (($gradedata['conditiongrademin'] !== '' || $gradedata['conditiongrademax'] !== '') && !$gradedata['conditiongradeitemid']) { $errors["conditiongradegroup[{$i}]"] = get_string('gradelimitsbutnoitem', 'condition'); continue; } } } // Conditions: Verify that the user profile field has not been declared more than once if (array_key_exists('conditionfieldgroup', $data)) { // Array to store the existing fields $arrcurrentfields = array(); // Error message displayed if any condition is declared more than once. We use lang string because // this way we don't actually generate the string unless there is an error. $stralreadydeclaredwarning = new lang_string('fielddeclaredmultipletimes', 'condition'); foreach ($data['conditionfieldgroup'] as $i => $fielddata) { if ($fielddata['conditionfield'] == 0) { // Don't need to bother if none is selected continue; } if (in_array($fielddata['conditionfield'], $arrcurrentfields)) { $errors["conditionfieldgroup[{$i}]"] = $stralreadydeclaredwarning->out(); } // Add the field to the array $arrcurrentfields[] = $fielddata['conditionfield']; } } return $errors; }
/** * Loop through uploaded grades and update the grades for this assignment * * @param int $draftid - The unique draft item id for this import * @param int $importid - The unique import ID for this csv import operation * @param bool $ignoremodified - Ignore the last modified date when checking fields * @return string - The html response */ public function process_import_grades($draftid, $importid, $ignoremodified) { global $USER, $DB; require_sesskey(); require_capability('mod/assign:grade', $this->assignment->get_context()); $gradeimporter = new assignfeedback_offline_grade_importer($importid, $this->assignment); $context = context_user::instance($USER->id); $fs = get_file_storage(); if (!($files = $fs->get_area_files($context->id, 'user', 'draft', $draftid, 'id DESC', false))) { redirect(new moodle_url('view.php', array('id' => $this->assignment->get_course_module()->id, 'action' => 'grading'))); return; } $file = reset($files); $csvdata = $file->get_content(); if ($csvdata) { $gradeimporter->parsecsv($csvdata); } if (!$gradeimporter->init()) { $thisurl = new moodle_url('/mod/assign/view.php', array('action' => 'viewpluginpage', 'pluginsubtype' => 'assignfeedback', 'plugin' => 'offline', 'pluginaction' => 'uploadgrades', 'id' => $assignment->get_course_module()->id)); print_error('invalidgradeimport', 'assignfeedback_offline', $thisurl); return; } // Does this assignment use a scale? $scaleoptions = null; if ($this->assignment->get_instance()->grade < 0) { if ($scale = $DB->get_record('scale', array('id' => -$this->assignment->get_instance()->grade))) { $scaleoptions = make_menu_from_list($scale->scale); } } // We may need to upgrade the gradebook comments after this update. $adminconfig = $this->assignment->get_admin_config(); $gradebookplugin = $adminconfig->feedback_plugin_for_gradebook; $updatecount = 0; while ($record = $gradeimporter->next()) { $user = $record->user; $modified = $record->modified; $userdesc = fullname($user); $usergrade = $this->assignment->get_user_grade($user->id, false); if (!empty($scaleoptions)) { // This is a scale - we need to convert any grades to indexes in the scale. $scaleindex = array_search($record->grade, $scaleoptions); if ($scaleindex !== false) { $record->grade = $scaleindex; } else { $record->grade = ''; } } else { $record->grade = unformat_float($record->grade); } // Note: Do not count the seconds when comparing modified dates. $skip = false; $stalemodificationdate = $usergrade && $usergrade->timemodified > $modified + 60; if ($usergrade && $usergrade->grade == $record->grade) { // Skip - grade not modified. $skip = true; } else { if (!isset($record->grade) || $record->grade === '' || $record->grade < 0) { // Skip - grade has no value. $skip = true; } else { if (!$ignoremodified && $stalemodificationdate) { // Skip - grade has been modified. $skip = true; } else { if ($this->assignment->grading_disabled($record->user->id)) { // Skip grade is locked. $skip = true; } else { if ($this->assignment->get_instance()->grade > -1 && ($record->grade < 0 || $record->grade > $this->assignment->get_instance()->grade)) { // Out of range. $skip = true; } } } } } if (!$skip) { $grade = $this->assignment->get_user_grade($record->user->id, true); $grade->grade = $record->grade; $grade->grader = $USER->id; if ($this->assignment->update_grade($grade)) { $this->assignment->notify_grade_modified($grade); $updatecount += 1; } } if ($ignoremodified || !$stalemodificationdate) { foreach ($record->feedback as $feedback) { $plugin = $feedback['plugin']; $field = $feedback['field']; $newvalue = $feedback['value']; $description = $feedback['description']; $oldvalue = ''; if ($usergrade) { $oldvalue = $plugin->get_editor_text($field, $usergrade->id); if (empty($oldvalue)) { $oldvalue = ''; } } if ($newvalue != $oldvalue) { $updatecount += 1; $grade = $this->assignment->get_user_grade($record->user->id, true); $this->assignment->notify_grade_modified($grade); $plugin->set_editor_text($field, $newvalue, $grade->id); // If this is the gradebook comments plugin - post an update to the gradebook. if ($plugin->get_subtype() . '_' . $plugin->get_type() == $gradebookplugin) { $grade->feedbacktext = $plugin->text_for_gradebook($grade); $grade->feedbackformat = $plugin->format_for_gradebook($grade); $this->assignment->update_grade($grade); } } } } } $gradeimporter->close(true); $renderer = $this->assignment->get_renderer(); $o = ''; $o .= $renderer->render(new assign_header($this->assignment->get_instance(), $this->assignment->get_context(), false, $this->assignment->get_course_module()->id, get_string('importgrades', 'assignfeedback_offline'))); $o .= $renderer->box(get_string('updatedgrades', 'assignfeedback_offline', $updatecount)); $url = new moodle_url('view.php', array('id' => $this->assignment->get_course_module()->id, 'action' => 'grading')); $o .= $renderer->continue_button($url); $o .= $renderer->render_footer(); return $o; }
function validation($data, $files) { global $COURSE, $DB, $CFG; $errors = parent::validation($data, $files); $mform =& $this->_form; $errors = array(); if ($mform->elementExists('name')) { $name = trim($data['name']); if ($name == '') { $errors['name'] = get_string('required'); } } $grade_item = grade_item::fetch(array('itemtype' => 'mod', 'itemmodule' => $data['modulename'], 'iteminstance' => $data['instance'], 'itemnumber' => 0, 'courseid' => $COURSE->id)); if ($data['coursemodule']) { $cm = $DB->get_record('course_modules', array('id' => $data['coursemodule'])); } else { $cm = null; } if ($mform->elementExists('cmidnumber')) { // verify the idnumber if (!grade_verify_idnumber($data['cmidnumber'], $COURSE->id, $grade_item, $cm)) { $errors['cmidnumber'] = get_string('idnumbertaken'); } } // Ratings: Don't let them select an aggregate type without selecting a scale. // If the user has selected to use ratings but has not chosen a scale or set max points then the form is // invalid. If ratings have been selected then the user must select either a scale or max points. // This matches (horrible) logic in data_preprocessing. if (isset($data['assessed']) && $data['assessed'] > 0 && empty($data['scale'])) { $errors['assessed'] = get_string('scaleselectionrequired', 'rating'); } // Check that the grade pass is a valid number. $gradepassvalid = false; if (isset($data['gradepass'])) { if (unformat_float($data['gradepass'], true) === false) { $errors['gradepass'] = get_string('err_numeric', 'form'); } else { $gradepassvalid = true; } } // Grade to pass: ensure that the grade to pass is valid for points and scales. // If we are working with a scale, convert into a positive number for validation. if ($gradepassvalid && isset($data['gradepass']) && (!empty($data['grade']) || !empty($data['scale']))) { $scale = !empty($data['grade']) ? $data['grade'] : $data['scale']; if ($scale < 0) { $scalevalues = $DB->get_record('scale', array('id' => -$scale)); $grade = count(explode(',', $scalevalues->scale)); } else { $grade = $scale; } if ($data['gradepass'] > $grade) { $errors['gradepass'] = get_string('gradepassgreaterthangrade', 'grades', $grade); } } // Completion: Don't let them choose automatic completion without turning // on some conditions. Ignore this check when completion settings are // locked, as the options are then disabled. if (array_key_exists('completion', $data) && $data['completion'] == COMPLETION_TRACKING_AUTOMATIC && !empty($data['completionunlocked'])) { if (empty($data['completionview']) && empty($data['completionusegrade']) && !$this->completion_rule_enabled($data)) { $errors['completion'] = get_string('badautocompletion', 'completion'); } } // Availability: Check availability field does not have errors. if (!empty($CFG->enableavailability)) { \core_availability\frontend::report_validation_errors($data, $errors); } return $errors; }
public function validation($data, $files) { $errors = parent::validation($data, $files); // Conditions: Don't let them set dates which make no sense if (array_key_exists('availablefrom', $data) && $data['availablefrom'] && $data['availableuntil'] && $data['availablefrom'] >= $data['availableuntil']) { $errors['availablefrom'] = get_string('badavailabledates', 'condition'); } // Conditions: Verify that the grade conditions are numbers, and make sense. if (array_key_exists('conditiongradegroup', $data)) { foreach ($data['conditiongradegroup'] as $i => $gradedata) { if ($gradedata['conditiongrademin'] !== '' && !is_numeric(unformat_float($gradedata['conditiongrademin']))) { $errors["conditiongradegroup[{$i}]"] = get_string('gradesmustbenumeric', 'condition'); continue; } if ($gradedata['conditiongrademax'] !== '' && !is_numeric(unformat_float($gradedata['conditiongrademax']))) { $errors["conditiongradegroup[{$i}]"] = get_string('gradesmustbenumeric', 'condition'); continue; } if ($gradedata['conditiongrademin'] !== '' && $gradedata['conditiongrademax'] !== '' && unformat_float($gradedata['conditiongrademax']) <= unformat_float($gradedata['conditiongrademin'])) { $errors["conditiongradegroup[{$i}]"] = get_string('badgradelimits', 'condition'); continue; } if ($gradedata['conditiongrademin'] === '' && $gradedata['conditiongrademax'] === '' && $gradedata['conditiongradeitemid']) { $errors["conditiongradegroup[{$i}]"] = get_string('gradeitembutnolimits', 'condition'); continue; } if (($gradedata['conditiongrademin'] !== '' || $gradedata['conditiongrademax'] !== '') && !$gradedata['conditiongradeitemid']) { $errors["conditiongradegroup[{$i}]"] = get_string('gradelimitsbutnoitem', 'condition'); continue; } } } // Conditions: Verify that the user profile field has not been declared more than once if (array_key_exists('conditionfieldgroup', $data)) { // Array to store the existing fields $arrcurrentfields = array(); // Error message displayed if any condition is declared more than once. We use lang string because // this way we don't actually generate the string unless there is an error. $stralreadydeclaredwarning = new lang_string('fielddeclaredmultipletimes', 'condition'); foreach ($data['conditionfieldgroup'] as $i => $fielddata) { if ($fielddata['conditionfield'] == 0) { // Don't need to bother if none is selected continue; } if (in_array($fielddata['conditionfield'], $arrcurrentfields)) { $errors["conditionfieldgroup[{$i}]"] = $stralreadydeclaredwarning->out(); } // Add the field to the array $arrcurrentfields[] = $fielddata['conditionfield']; } } return $errors; }
/** * Apply a grade from a grading form to a user (may be called multiple times for a group submission). * * @param stdClass $formdata - the data from the form * @param int $userid - the user to apply the grade to * @param int $attemptnumber - The attempt number to apply the grade to. * @return void */ protected function apply_grade_to_user($formdata, $userid, $attemptnumber) { global $USER, $CFG, $DB; $grade = $this->get_user_grade($userid, true, $attemptnumber); $originalgrade = $grade->grade; $gradingdisabled = $this->grading_disabled($userid); $gradinginstance = $this->get_grading_instance($userid, $grade, $gradingdisabled); if (!$gradingdisabled) { if ($gradinginstance) { $grade->grade = $gradinginstance->submit_and_get_grade($formdata->advancedgrading, $grade->id); } else { // Handle the case when grade is set to No Grade. if (isset($formdata->grade)) { $grade->grade = grade_floatval(unformat_float($formdata->grade)); } } if (isset($formdata->workflowstate) || isset($formdata->allocatedmarker)) { $flags = $this->get_user_flags($userid, true); $oldworkflowstate = $flags->workflowstate; $flags->workflowstate = isset($formdata->workflowstate) ? $formdata->workflowstate : $flags->workflowstate; $flags->allocatedmarker = isset($formdata->allocatedmarker) ? $formdata->allocatedmarker : $flags->allocatedmarker; if ($this->update_user_flags($flags) && isset($formdata->workflowstate) && $formdata->workflowstate !== $oldworkflowstate) { $user = $DB->get_record('user', array('id' => $userid), '*', MUST_EXIST); \mod_assign\event\workflow_state_updated::create_from_user($this, $user, $formdata->workflowstate)->trigger(); } } } $grade->grader = $USER->id; $adminconfig = $this->get_admin_config(); $gradebookplugin = $adminconfig->feedback_plugin_for_gradebook; // Call save in plugins. foreach ($this->feedbackplugins as $plugin) { if ($plugin->is_enabled() && $plugin->is_visible()) { if (!$plugin->save($grade, $formdata)) { $result = false; print_error($plugin->get_error()); } if ('assignfeedback_' . $plugin->get_type() == $gradebookplugin) { // This is the feedback plugin chose to push comments to the gradebook. $grade->feedbacktext = $plugin->text_for_gradebook($grade); $grade->feedbackformat = $plugin->format_for_gradebook($grade); } } } // We do not want to update the timemodified if no grade was added. if (!empty($formdata->addattempt) || $originalgrade !== null && $originalgrade != -1 || $grade->grade !== null && $grade->grade != -1) { $this->update_grade($grade, !empty($formdata->addattempt)); } // Note the default if not provided for this option is true (e.g. webservices). // This is for backwards compatibility. if (!isset($formdata->sendstudentnotifications) || $formdata->sendstudentnotifications) { $this->notify_grade_modified($grade, true); } }
/** * Processes the data sent by the form (grades and feedbacks). * Caller is responsible for all access control checks * @param array $data form submission (with magic quotes) * @return array empty array if success, array of warnings if something fails. */ public function process_data($data) { global $DB; $warnings = array(); $separategroups = false; $mygroups = array(); if ($this->groupmode == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $this->context)) { $separategroups = true; $mygroups = groups_get_user_groups($this->course->id); $mygroups = $mygroups[0]; // ignore groupings // reorder the groups fro better perf below $current = array_search($this->currentgroup, $mygroups); if ($current !== false) { unset($mygroups[$current]); array_unshift($mygroups, $this->currentgroup); } } // always initialize all arrays $queue = array(); $this->load_users(); $this->load_final_grades(); // Were any changes made? $changedgrades = false; $timepageload = clean_param($data->timepageload, PARAM_INT); foreach ($data as $varname => $students) { $needsupdate = false; // skip, not a grade nor feedback if (strpos($varname, 'grade') === 0) { $datatype = 'grade'; } else { if (strpos($varname, 'feedback') === 0) { $datatype = 'feedback'; } else { continue; } } foreach ($students as $userid => $items) { $userid = clean_param($userid, PARAM_INT); foreach ($items as $itemid => $postedvalue) { $itemid = clean_param($itemid, PARAM_INT); // Was change requested? $oldvalue = $this->grades[$userid][$itemid]; if ($datatype === 'grade') { // If there was no grade and there still isn't if (is_null($oldvalue->finalgrade) && $postedvalue == -1) { // -1 means no grade continue; } // If the grade item uses a custom scale if (!empty($oldvalue->grade_item->scaleid)) { if ((int) $oldvalue->finalgrade === (int) $postedvalue) { continue; } } else { // The grade item uses a numeric scale // Format the finalgrade from the DB so that it matches the grade from the client if ($postedvalue === format_float($oldvalue->finalgrade, $oldvalue->grade_item->get_decimals())) { continue; } } $changedgrades = true; } else { if ($datatype === 'feedback') { // If quick grading is on, feedback needs to be compared without line breaks. if ($this->get_pref('quickgrading')) { $oldvalue->feedback = preg_replace("/\r\n|\r|\n/", "", $oldvalue->feedback); } if ($oldvalue->feedback === $postedvalue or $oldvalue->feedback === null and empty($postedvalue)) { continue; } } } if (!($gradeitem = grade_item::fetch(array('id' => $itemid, 'courseid' => $this->courseid)))) { print_error('invalidgradeitemid'); } // Pre-process grade if ($datatype == 'grade') { $feedback = false; $feedbackformat = false; if ($gradeitem->gradetype == GRADE_TYPE_SCALE) { if ($postedvalue == -1) { // -1 means no grade $finalgrade = null; } else { $finalgrade = $postedvalue; } } else { $finalgrade = unformat_float($postedvalue); } $errorstr = ''; $skip = false; $dategraded = $oldvalue->get_dategraded(); if (!empty($dategraded) && $timepageload < $dategraded) { // Warn if the grade was updated while we were editing this form. $errorstr = 'gradewasmodifiedduringediting'; $skip = true; } else { if (!is_null($finalgrade)) { // Warn if the grade is out of bounds. $bounded = $gradeitem->bounded_grade($finalgrade); if ($bounded > $finalgrade) { $errorstr = 'lessthanmin'; } else { if ($bounded < $finalgrade) { $errorstr = 'morethanmax'; } } } } if ($errorstr) { $userfields = 'id, ' . get_all_user_name_fields(true); $user = $DB->get_record('user', array('id' => $userid), $userfields); $gradestr = new stdClass(); $gradestr->username = fullname($user); $gradestr->itemname = $gradeitem->get_name(); $warnings[] = get_string($errorstr, 'grades', $gradestr); if ($skip) { // Skipping the update of this grade it failed the tests above. continue; } } } else { if ($datatype == 'feedback') { $finalgrade = false; $trimmed = trim($postedvalue); if (empty($trimmed)) { $feedback = null; } else { $feedback = $postedvalue; } } } // group access control if ($separategroups) { // note: we can not use $this->currentgroup because it would fail badly // when having two browser windows each with different group $sharinggroup = false; foreach ($mygroups as $groupid) { if (groups_is_member($groupid, $userid)) { $sharinggroup = true; break; } } if (!$sharinggroup) { // either group membership changed or somebody is hacking grades of other group $warnings[] = get_string('errorsavegrade', 'grades'); continue; } } $gradeitem->update_final_grade($userid, $finalgrade, 'gradebook', $feedback, FORMAT_MOODLE); // We can update feedback without reloading the grade item as it doesn't affect grade calculations if ($datatype === 'feedback') { $this->grades[$userid][$itemid]->feedback = $feedback; } } } } if ($changedgrades) { // If a final grade was overriden reload grades so dependent grades like course total will be correct $this->grades = null; } return $warnings; }
} if (!isset($itemdata->grademin) || $itemdata->grademin == '') { $itemdata->grademin = 0; } $hidden = empty($itemdata->hidden) ? 0 : $itemdata->hidden; $hiddenuntil = empty($itemdata->hiddenuntil) ? 0 : $itemdata->hiddenuntil; unset($itemdata->hidden); unset($itemdata->hiddenuntil); $locked = empty($itemdata->locked) ? 0 : $itemdata->locked; $locktime = empty($itemdata->locktime) ? 0 : $itemdata->locktime; unset($itemdata->locked); unset($itemdata->locktime); $convert = array('grademax', 'grademin', 'gradepass', 'multfactor', 'plusfactor', 'aggregationcoef', 'aggregationcoef2'); foreach ($convert as $param) { if (property_exists($itemdata, $param)) { $itemdata->{$param} = unformat_float($itemdata->{$param}); } } if (isset($itemdata->aggregationcoef2)) { $itemdata->aggregationcoef2 = $itemdata->aggregationcoef2 / 100.0; } // When creating a new category, a number of grade item fields are filled out automatically, and are required. // If the user leaves these fields empty during creation of a category, we let the default values take effect // Otherwise, we let the user-entered grade item values take effect $grade_item = $grade_category->load_grade_item(); $grade_item_copy = fullclone($grade_item); grade_item::set_properties($grade_item, $itemdata); if (empty($grade_item->id)) { $grade_item->id = $grade_item_copy->id; } if (empty($grade_item->grademax) && $grade_item->grademax != '0') {
// form processing } else { if ($data = $mform->get_data(false)) { $old_grade_grade = new grade_grade(array('userid' => $data->userid, 'itemid' => $grade_item->id), true); //might not exist yet // fix no grade for scales if (!isset($data->finalgrade) or $data->finalgrade == $data->oldgrade) { $data->finalgrade = $old_grade_grade->finalgrade; } else { if ($grade_item->gradetype == GRADE_TYPE_SCALE) { if ($data->finalgrade < 1) { $data->finalgrade = NULL; } } else { if ($grade_item->gradetype == GRADE_TYPE_VALUE) { $data->finalgrade = unformat_float($data->finalgrade); } else { //this shoul not happen $data->finalgrade = $old_grade_grade->finalgrade; } } } // the overriding of feedback is tricky - we have to care about external items only if (!array_key_exists('feedback', $data) or $data->feedback == $data->oldfeedback) { $data->feedback = $old_grade_grade->feedback; $data->feedbackformat = $old_grade_grade->feedbackformat; } // update final grade or feedback $grade_item->update_final_grade($data->userid, $data->finalgrade, 'editgrade', $data->feedback, $data->feedbackformat); $grade_grade = new grade_grade(array('userid' => $data->userid, 'itemid' => $grade_item->id), true); $grade_grade->grade_item =& $grade_item;
/** * Apply a grade from a grading form to a user (may be called multiple times for a group submission). * * @param stdClass $formdata - the data from the form * @param int $userid - the user to apply the grade to * @param int $attemptnumber - The attempt number to apply the grade to. * @return void */ protected function apply_grade_to_user($formdata, $userid, $attemptnumber) { global $USER, $CFG, $DB; $grade = $this->get_user_grade($userid, true, $attemptnumber); $gradingdisabled = $this->grading_disabled($userid); $gradinginstance = $this->get_grading_instance($userid, $grade, $gradingdisabled); if (!$gradingdisabled) { if ($gradinginstance) { $grade->grade = $gradinginstance->submit_and_get_grade($formdata->advancedgrading, $grade->id); } else { // Handle the case when grade is set to No Grade. if (isset($formdata->grade)) { $grade->grade = grade_floatval(unformat_float($formdata->grade)); } } if (isset($formdata->workflowstate) || isset($formdata->allocatedmarker)) { $flags = $this->get_user_flags($userid, true); $flags->workflowstate = isset($formdata->workflowstate) ? $formdata->workflowstate : $flags->workflowstate; $flags->allocatedmarker = isset($formdata->allocatedmarker) ? $formdata->allocatedmarker : $flags->allocatedmarker; $this->update_user_flags($flags); } } $grade->grader = $USER->id; $adminconfig = $this->get_admin_config(); $gradebookplugin = $adminconfig->feedback_plugin_for_gradebook; // Call save in plugins. foreach ($this->feedbackplugins as $plugin) { if ($plugin->is_enabled() && $plugin->is_visible()) { if (!$plugin->save($grade, $formdata)) { $result = false; print_error($plugin->get_error()); } if ('assignfeedback_' . $plugin->get_type() == $gradebookplugin) { // This is the feedback plugin chose to push comments to the gradebook. $grade->feedbacktext = $plugin->text_for_gradebook($grade); $grade->feedbackformat = $plugin->format_for_gradebook($grade); } } } $this->update_grade($grade); $this->notify_grade_modified($grade); $addtolog = $this->add_to_log('grade submission', $this->format_grade_for_log($grade), '', true); $params = array('context' => $this->context, 'objectid' => $grade->id, 'relateduserid' => $userid); $event = \mod_assign\event\submission_graded::create($params); $event->set_legacy_logdata($addtolog); $event->trigger(); }
/** * Processes the data sent by the form (grades and feedbacks). * Caller is reposible for all access control checks * @param array $data form submission (with magic quotes) * @return array empty array if success, array of warnings if something fails. */ function process_data($data) { $warnings = array(); $separategroups = false; $mygroups = array(); if ($this->groupmode == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $this->context)) { $separategroups = true; $mygroups = groups_get_user_groups($this->course->id); $mygroups = $mygroups[0]; // ignore groupings // reorder the groups fro better perf bellow $current = array_search($this->currentgroup, $mygroups); if ($current !== false) { unset($mygroups[$current]); array_unshift($mygroups, $this->currentgroup); } } // always initialize all arrays $queue = array(); foreach ($data as $varname => $postedvalue) { $needsupdate = false; // skip, not a grade nor feedback if (strpos($varname, 'grade') === 0) { $data_type = 'grade'; } else { if (strpos($varname, 'feedback') === 0) { $data_type = 'feedback'; } else { continue; } } $gradeinfo = explode("_", $varname); $userid = clean_param($gradeinfo[1], PARAM_INT); $itemid = clean_param($gradeinfo[2], PARAM_INT); $oldvalue = $data->{'old' . $varname}; // was change requested? if ($oldvalue == $postedvalue) { // string comparison continue; } if (!($grade_item = grade_item::fetch(array('id' => $itemid, 'courseid' => $this->courseid)))) { // we must verify course id here! error('Incorrect grade item id'); } // Pre-process grade if ($data_type == 'grade') { $feedback = false; $feedbackformat = false; if ($grade_item->gradetype == GRADE_TYPE_SCALE) { if ($postedvalue == -1) { // -1 means no grade $finalgrade = null; } else { $finalgrade = $postedvalue; } } else { $finalgrade = unformat_float($postedvalue); } $errorstr = ''; // Warn if the grade is out of bounds. if (is_null($finalgrade)) { // ok } else { $bounded = $grade_item->bounded_grade($finalgrade); if ($bounded > $finalgrade) { $errorstr = 'lessthanmin'; } else { if ($bounded < $finalgrade) { $errorstr = 'morethanmax'; } } } if ($errorstr) { $user = get_record('user', 'id', $userid, '', '', '', '', 'id, firstname, lastname'); $gradestr = new object(); $gradestr->username = fullname($user); $gradestr->itemname = $grade_item->get_name(); $warnings[] = get_string($errorstr, 'grades', $gradestr); } } else { if ($data_type == 'feedback') { $finalgrade = false; $trimmed = trim($postedvalue); if (empty($trimmed)) { $feedback = NULL; } else { $feedback = stripslashes($postedvalue); } } } // group access control if ($separategroups) { // note: we can not use $this->currentgroup because it would fail badly // when having two browser windows each with different group $sharinggroup = false; foreach ($mygroups as $groupid) { if (groups_is_member($groupid, $userid)) { $sharinggroup = true; break; } } if (!$sharinggroup) { // either group membership changed or somebedy is hacking grades of other group $warnings[] = get_string('errorsavegrade', 'grades'); continue; } } $grade_item->update_final_grade($userid, $finalgrade, 'gradebook', $feedback, FORMAT_MOODLE); } return $warnings; }
if ($data = data_submitted() and confirm_sesskey()) { // Perform bulk actions first if (!empty($data->bulkmove)) { $elements = array(); foreach ($data as $key => $value) { if (preg_match('/select_(ig[0-9]*)/', $key, $matches)) { $elements[] = $matches[1]; } } $grade_edit_tree->move_elements($elements, $returnurl); } // Update weights (extra credits) on categories and items. foreach ($data as $key => $value) { if (preg_match('/^weight_([0-9]+)$/', $key, $matches)) { $aid = $matches[1]; $value = unformat_float($value); $value = clean_param($value, PARAM_FLOAT); $grade_item = grade_item::fetch(array('id' => $aid, 'courseid' => $courseid)); // Convert weight to aggregation coef2. $aggcoef = $grade_item->get_coefstring(); if ($aggcoef == 'aggregationcoefextraweightsum') { // The field 'weight' should only be sent when the checkbox 'weighoverride' is checked, // so there is not need to set weightoverride here, it is done below. $value = $value / 100.0; $grade_item->aggregationcoef2 = $value; } else { if ($aggcoef == 'aggregationcoefweight' || $aggcoef == 'aggregationcoefextraweight') { $grade_item->aggregationcoef = $value; } } $grade_item->update();
function update_content($recordid, $value, $name = '') { global $DB; $content = new stdClass(); $content->fieldid = $this->field->id; $content->recordid = $recordid; // When updating these values (which might be region formatted) we should format // the float to allow for a consistent float format in the database. $value = unformat_float($value); $value = trim($value); if (strlen($value) > 0) { $value = floatval($value); } else { $value = null; } $names = explode('_', $name); switch ($names[2]) { case 0: // update lat $content->content = $value; break; case 1: // update long $content->content1 = $value; break; default: break; } if ($oldcontent = $DB->get_record('data_content', array('fieldid' => $this->field->id, 'recordid' => $recordid))) { $content->id = $oldcontent->id; return $DB->update_record('data_content', $content); } else { return $DB->insert_record('data_content', $content); } }