/** * Tests update score without sending item details. * Grade item should not be created without item name. * * @return void */ public function test_update_score() { global $DB; $this->set_user('admin'); $this->assertEquals(0, $DB->count_records('grade_items')); // Add an mhaairs item directly. $iteminstance = 24993; $itemparams = array('courseid' => $this->course->id, 'itemtype' => 'manual', 'itemmodule' => 'mhaairs', 'iteminstance' => $iteminstance, 'itemname' => 'MH Assignment'); $gitem = new \grade_item($itemparams, false); $gitem->insert('mhaairs'); $this->assertEquals(2, $DB->count_records('grade_items')); $service = 'block_mhaairs_gradebookservice_external::update_grade'; $grades = array('userid' => 'student1', 'rawgrade' => 93); $gradesjson = urlencode(json_encode($grades)); $servicedata = array(); $servicedata['source'] = 'mhaairs'; $servicedata['courseid'] = 'tc1'; $servicedata['itemtype'] = 'manual'; $servicedata['itemmodule'] = 'mhaairs'; $servicedata['iteminstance'] = 111; $servicedata['itemnumber'] = 0; $servicedata['grades'] = $gradesjson; $servicedata['itemdetails'] = null; // Send score via service without details, item by instance doesn't exist. $result = call_user_func_array($service, $servicedata); $this->assertEquals(GRADE_UPDATE_FAILED, $result); $this->assertEquals(2, $DB->count_records('grade_items')); // Set the existing item instance. $servicedata['iteminstance'] = $iteminstance; // Send score via service without details, item by instance exists. $result = call_user_func_array($service, $servicedata); $this->assertEquals(GRADE_UPDATE_OK, $result); $this->assertEquals(2, $DB->count_records('grade_items')); $this->assertEquals(1, $DB->count_records('grade_grades')); $usergrade = $DB->get_field('grade_grades', 'finalgrade', array('userid' => $this->student1->id)); $this->assertEquals(93, $usergrade); // Set typical item details for score update. $itemdetails = array('courseid' => '3', 'idnumber' => '111', 'identity_type' => null, 'needsupdate' => 1, 'useexisting' => 0); $itemdetailsjson = urlencode(json_encode($grades)); $servicedata['itemdetails'] = $itemdetailsjson; $grades = array('userid' => 'student1', 'rawgrade' => 94); $gradesjson = urlencode(json_encode($grades)); $servicedata['grades'] = $gradesjson; // Send score via service to item with details. $result = call_user_func_array($service, $servicedata); $this->assertEquals(GRADE_UPDATE_OK, $result); $this->assertEquals(2, $DB->count_records('grade_items')); $this->assertEquals(1, $DB->count_records('grade_grades')); $usergrade = $DB->get_field('grade_grades', 'finalgrade', array('userid' => $this->student1->id)); $this->assertEquals(94, $usergrade); }
/** * Initialise the iterator * @return boolean success */ function init() { global $CFG; $this->close(); grade_regrade_final_grades($this->course->id); $course_item = grade_item::fetch_course_item($this->course->id); if ($course_item->needsupdate) { // can not calculate all final grades - sorry return false; } if (strpos($CFG->gradebookroles, ',') !== false) { $gradebookroles = " = {$CFG->gradebookroles}"; } else { $gradebookroles = " IN ({$CFG->gradebookroles})"; } $relatedcontexts = get_related_contexts_string(get_context_instance(CONTEXT_COURSE, $this->course->id)); if ($this->groupid) { $groupsql = "INNER JOIN {$CFG->prefix}groups_members gm ON gm.userid = u.id"; $groupwheresql = "AND gm.groupid = {$this->groupid}"; } else { $groupsql = ""; $groupwheresql = ""; } $users_sql = "SELECT u.*\n FROM {$CFG->prefix}user u\n INNER JOIN {$CFG->prefix}role_assignments ra ON u.id = ra.userid\n {$groupsql}\n WHERE ra.roleid {$gradebookroles}\n AND ra.contextid {$relatedcontexts}\n {$groupwheresql}\n ORDER BY u.id ASC"; $this->users_rs = get_recordset_sql($users_sql); if (!empty($this->grade_items)) { $itemids = array_keys($this->grade_items); $itemids = implode(',', $itemids); $grades_sql = "SELECT g.*\n FROM {$CFG->prefix}grade_grades g\n INNER JOIN {$CFG->prefix}user u ON g.userid = u.id\n INNER JOIN {$CFG->prefix}role_assignments ra ON u.id = ra.userid\n {$groupsql}\n WHERE ra.roleid {$gradebookroles}\n AND ra.contextid {$relatedcontexts}\n AND g.itemid IN ({$itemids})\n {$groupwheresql}\n ORDER BY g.userid ASC, g.itemid ASC"; $this->grades_rs = get_recordset_sql($grades_sql); } return true; }
function definition_after_data() { global $CFG, $COURSE; $mform =& $this->_form; if ($id = $mform->getElementValue('id')) { $grade_item = grade_item::fetch(array('id' => $id)); //remove the aggregation coef element if not needed if ($grade_item->is_course_item()) { $mform->removeElement('aggregationcoef'); } else { if ($grade_item->is_category_item()) { $category = $grade_item->get_item_category(); $parent_category = $category->get_parent_category(); if (!$parent_category->is_aggregationcoef_used()) { $mform->removeElement('aggregationcoef'); } } else { $parent_category = $grade_item->get_parent_category(); if (!$parent_category->is_aggregationcoef_used()) { $mform->removeElement('aggregationcoef'); } } } } else { $course_category = grade_category::fetch_course_category($COURSE->id); if (!$course_category->is_aggregationcoef_used()) { $mform->removeElement('aggregationcoef'); } } }
/** * Check grade hidden status. Uses data from both grade item and grade. * * @return int 0 means visible, 1 hidden always, timestamp hidden until */ public function get_hidden() { $this->load_grade_item(); $item_hidden = $this->grade_item->get_hidden(); if ($item_hidden == 1) { return 1; } else { if ($item_hidden == 0) { return $this->hidden; } else { if ($this->hidden == 0) { return $item_hidden; } else { if ($this->hidden == 1) { return 1; } else { if ($this->hidden > $item_hidden) { return $this->hidden; } else { return $item_hidden; } } } } } }
/** * Constructor should set up all the private variables ready to be pulled * @param object $course * @param int $groupid id of selected group, 0 means all * @param string $itemlist comma separated list of item ids, empty means all * @param boolean $export_feedback * @param boolean $export_letters * @note Exporting as letters will lead to data loss if that exported set it re-imported. */ function grade_export($course, $groupid = 0, $itemlist = '', $export_feedback = false, $updatedgradesonly = false, $displaytype = GRADE_DISPLAY_TYPE_REAL, $decimalpoints = 2) { $this->course = $course; $this->groupid = $groupid; $this->grade_items = grade_item::fetch_all(array('courseid' => $this->course->id)); $this->columns = array(); if (!empty($itemlist)) { $itemids = explode(',', $itemlist); // remove items that are not requested foreach ($itemids as $itemid) { if (array_key_exists($itemid, $this->grade_items)) { $this->columns[$itemid] =& $this->grade_items[$itemid]; } } } else { foreach ($this->grade_items as $itemid => $unused) { $this->columns[$itemid] =& $this->grade_items[$itemid]; } } $this->export_feedback = $export_feedback; $this->userkey = ''; $this->previewrows = false; $this->updatedgradesonly = $updatedgradesonly; $this->displaytype = $displaytype; $this->decimalpoints = $decimalpoints; }
protected function get_javascript_init_params($course, \cm_info $cm = null, \section_info $section = null) { global $DB, $CFG; require_once $CFG->libdir . '/gradelib.php'; require_once $CFG->dirroot . '/course/lib.php'; // Get grades as basic associative array. $gradeoptions = array(); $items = \grade_item::fetch_all(array('courseid' => $course->id)); // For some reason the fetch_all things return null if none. $items = $items ? $items : array(); foreach ($items as $id => $item) { // Don't include the grade item if it's linked with a module that is being deleted. if (course_module_instance_pending_deletion($item->courseid, $item->itemmodule, $item->iteminstance)) { continue; } // Do not include grades for current item. if ($cm && $cm->instance == $item->iteminstance && $cm->modname == $item->itemmodule && $item->itemtype == 'mod') { continue; } $gradeoptions[$id] = $item->get_name(true); } \core_collator::asort($gradeoptions); // Change to JS array format and return. $jsarray = array(); foreach ($gradeoptions as $id => $name) { $jsarray[] = (object) array('id' => $id, 'name' => $name); } return array($jsarray); }
function fill_table() { global $CFG; $numusers = $this->get_numusers(); if ($courses = get_courses('all', null, 'c.id, c.shortname')) { foreach ($courses as $course) { // Get course grade_item $grade_item = grade_item::fetch(array('itemtype' => 'course', 'courseid' => $course->id)); // Get the grade $finalgrade = get_field('grade_grades', 'finalgrade', 'itemid', $grade_item->id, 'userid', $this->user->id); /// prints rank if ($finalgrade) { /// find the number of users with a higher grade $sql = "SELECT COUNT(DISTINCT(userid))\n FROM {$CFG->prefix}grade_grades\n WHERE finalgrade > {$finalgrade}\n AND itemid = {$grade_item->id}"; $rank = count_records_sql($sql) + 1; $rankdata = "{$rank}/{$numusers}"; } else { // no grade, no rank $rankdata = "-"; } $courselink = '<a href="' . $CFG->wwwroot . '/grade/report/user/index.php?id=' . $course->id . '">' . $course->shortname . '</a>'; $this->table->add_data(array($courselink, round(grade_to_percentage($finalgrade, $grade_item->grademin, $grade_item->grademax), 1) . '%', $rankdata)); } return true; } else { notify(get_string('nocourses', 'grades')); return false; } }
/** * Constructor should set up all the private variables ready to be pulled * @param object $course * @param int $groupid id of selected group, 0 means all * @param string $itemlist comma separated list of item ids, empty means all * @param boolean $export_feedback * @param boolean $export_letters * @note Exporting as letters will lead to data loss if that exported set it re-imported. */ function grade_export($course, $groupid = 0, $itemlist = '', $export_feedback = false, $updatedgradesonly = false, $displaytype = GRADE_DISPLAY_TYPE_REAL, $decimalpoints = 2) { $this->course = $course; $this->groupid = $groupid; $this->grade_items = grade_item::fetch_all(array('courseid' => $this->course->id)); //Populating the columns here is required by /grade/export/(whatever)/export.php //however index.php, when the form is submitted, will construct the collection here //with an empty $itemlist then reconstruct it in process_form() using $formdata $this->columns = array(); if (!empty($itemlist)) { if ($itemlist == '-1') { //user deselected all items } else { $itemids = explode(',', $itemlist); // remove items that are not requested foreach ($itemids as $itemid) { if (array_key_exists($itemid, $this->grade_items)) { $this->columns[$itemid] =& $this->grade_items[$itemid]; } } } } else { foreach ($this->grade_items as $itemid => $unused) { $this->columns[$itemid] =& $this->grade_items[$itemid]; } } $this->export_feedback = $export_feedback; $this->userkey = ''; $this->previewrows = false; $this->updatedgradesonly = $updatedgradesonly; $this->displaytype = $displaytype; $this->decimalpoints = $decimalpoints; }
/** * Tests the backup and restore of single activity to same course (duplicate) * when it contains fields and views. */ public function test_duplicate() { global $DB, $CFG; $this->resetAfterTest(true); $this->setAdminUser(); $generator = $this->getDataGenerator(); $dataformgenerator = $generator->get_plugin_generator('mod_dataform'); // Create a course. $course = $generator->create_course(); // DATAFORM 1. $params = array('course' => $course->id, 'grade' => 100); $dataform1 = $dataformgenerator->create_instance($params); $df1 = mod_dataform_dataform::instance($dataform1->id); // Add fields. $fieldtypes = array_keys(core_component::get_plugin_list('dataformfield')); $fieldtypescount = count($fieldtypes); foreach ($fieldtypes as $type) { $df1->field_manager->add_field($type); } // Add views. $viewtypes = array_keys(core_component::get_plugin_list('dataformview')); $viewtypescount = count($viewtypes); foreach ($viewtypes as $type) { $df1->view_manager->add_view($type); } // Fetch the grade item. $params = array('itemtype' => 'mod', 'itemmodule' => 'dataform', 'iteminstance' => $dataform1->id, 'courseid' => $course->id, 'itemnumber' => 0); $gradeitem1 = grade_item::fetch($params); // Check number of dataforms. $this->assertEquals(1, $DB->count_records('dataform')); // Check number of fields. $this->assertEquals($fieldtypescount, $DB->count_records('dataform_fields')); $this->assertEquals($fieldtypescount, $DB->count_records('dataform_fields', array('dataid' => $dataform1->id))); // Check number of views. $this->assertEquals($viewtypescount, $DB->count_records('dataform_views')); $this->assertEquals($viewtypescount, $DB->count_records('dataform_views', array('dataid' => $dataform1->id))); // Check number of filters. // $this->assertEquals(2, $DB->count_records('dataform_filters')); // $this->assertEquals(2, $DB->count_records('dataform_filters', array('dataid' => $dataform1->id)));. // DUPLICATE the dataform instance. $dataform2 = $dataformgenerator->duplicate_instance($course, $dataform1->cmid); // Check number of dataforms. $this->assertEquals(2, $DB->count_records('dataform')); // Check duplication of fields. $this->assertEquals($fieldtypescount * 2, $DB->count_records('dataform_fields')); $this->assertEquals($fieldtypescount, $DB->count_records('dataform_fields', array('dataid' => $dataform1->id))); $this->assertEquals($fieldtypescount, $DB->count_records('dataform_fields', array('dataid' => $dataform2->id))); // Check duplication of views. $this->assertEquals($viewtypescount * 2, $DB->count_records('dataform_views')); $this->assertEquals($viewtypescount, $DB->count_records('dataform_views', array('dataid' => $dataform1->id))); $this->assertEquals($viewtypescount, $DB->count_records('dataform_views', array('dataid' => $dataform2->id))); // Check number of filters. // $this->assertEquals(4, $DB->count_records('dataform_filters'); // $this->assertEquals(2, $DB->count_records('dataform_filters', array('dataid' => $dataform1->id)); // $this->assertEquals(2, $DB->count_records('dataform_filters', array('dataid' => $dataform2->id));. // Dataform cleanup. $dataformgenerator->delete_all_instances(); }
/** * Initialise the iterator * @return boolean success */ public function init() { global $CFG, $DB; $this->close(); grade_regrade_final_grades($this->course->id); $course_item = grade_item::fetch_course_item($this->course->id); if ($course_item->needsupdate) { // can not calculate all final grades - sorry return false; } $coursecontext = get_context_instance(CONTEXT_COURSE, $this->course->id); $relatedcontexts = get_related_contexts_string($coursecontext); list($gradebookroles_sql, $params) = $DB->get_in_or_equal(explode(',', $CFG->gradebookroles), SQL_PARAMS_NAMED, 'grbr'); //limit to users with an active enrolment list($enrolledsql, $enrolledparams) = get_enrolled_sql($coursecontext); $params = array_merge($params, $enrolledparams); if ($this->groupid) { $groupsql = "INNER JOIN {groups_members} gm ON gm.userid = u.id"; $groupwheresql = "AND gm.groupid = :groupid"; // $params contents: gradebookroles $params['groupid'] = $this->groupid; } else { $groupsql = ""; $groupwheresql = ""; } if (empty($this->sortfield1)) { // we must do some sorting even if not specified $ofields = ", u.id AS usrt"; $order = "usrt ASC"; } else { $ofields = ", u.{$this->sortfield1} AS usrt1"; $order = "usrt1 {$this->sortorder1}"; if (!empty($this->sortfield2)) { $ofields .= ", u.{$this->sortfield2} AS usrt2"; $order .= ", usrt2 {$this->sortorder2}"; } if ($this->sortfield1 != 'id' and $this->sortfield2 != 'id') { // user order MUST be the same in both queries, // must include the only unique user->id if not already present $ofields .= ", u.id AS usrt"; $order .= ", usrt ASC"; } } // $params contents: gradebookroles and groupid (for $groupwheresql) $users_sql = "SELECT u.* {$ofields}\n FROM {user} u\n JOIN ({$enrolledsql}) je ON je.id = u.id\n {$groupsql}\n JOIN (\n SELECT DISTINCT ra.userid\n FROM {role_assignments} ra\n WHERE ra.roleid {$gradebookroles_sql}\n AND ra.contextid {$relatedcontexts}\n ) rainner ON rainner.userid = u.id\n WHERE u.deleted = 0\n {$groupwheresql}\n ORDER BY {$order}"; $this->users_rs = $DB->get_recordset_sql($users_sql, $params); if (!empty($this->grade_items)) { $itemids = array_keys($this->grade_items); list($itemidsql, $grades_params) = $DB->get_in_or_equal($itemids, SQL_PARAMS_NAMED, 'items'); $params = array_merge($params, $grades_params); // $params contents: gradebookroles, enrolledparams, groupid (for $groupwheresql) and itemids $grades_sql = "SELECT g.* {$ofields}\n FROM {grade_grades} g\n JOIN {user} u ON g.userid = u.id\n JOIN ({$enrolledsql}) je ON je.id = u.id\n {$groupsql}\n JOIN (\n SELECT DISTINCT ra.userid\n FROM {role_assignments} ra\n WHERE ra.roleid {$gradebookroles_sql}\n AND ra.contextid {$relatedcontexts}\n ) rainner ON rainner.userid = u.id\n WHERE u.deleted = 0\n AND g.itemid {$itemidsql}\n {$groupwheresql}\n ORDER BY {$order}, g.itemid ASC"; $this->grades_rs = $DB->get_recordset_sql($grades_sql, $params); } else { $this->grades_rs = false; } return true; }
/** * Tests grade_report_grader::process_data() * * process_data() processes submitted grade and feedback data */ public function test_process_data() { global $DB, $CFG; $this->resetAfterTest(true); $course = $this->getDataGenerator()->create_course(); // Create and enrol a student. $student = $this->getDataGenerator()->create_user(array('username' => 'Student Sam')); $role = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST); $this->getDataGenerator()->enrol_user($student->id, $course->id, $role->id); // Test with limited grades. $CFG->unlimitedgrades = 0; $forummax = 80; $forum1 = $this->getDataGenerator()->create_module('forum', array('assessed' => 1, 'scale' => $forummax, 'course' => $course->id)); // Switch the stdClass instance for a grade item instance. $forum1 = grade_item::fetch(array('itemtype' => 'mod', 'itemmodule' => 'forum', 'iteminstance' => $forum1->id, 'courseid' => $course->id)); $report = $this->create_report($course); $testgrade = 60.0; $data = new stdClass(); $data->id = $course->id; $data->report = 'grader'; $data->timepageload = time(); $data->grade = array(); $data->grade[$student->id] = array(); $data->grade[$student->id][$forum1->id] = $testgrade; $warnings = $report->process_data($data); $this->assertEquals(count($warnings), 0); $studentgrade = grade_grade::fetch(array('itemid' => $forum1->id, '' => $student->id)); $this->assertEquals($studentgrade->finalgrade, $testgrade); // Grade above max. Should be pulled down to max. $toobig = 200.0; $data->grade[$student->id][$forum1->id] = $toobig; $data->timepageload = time(); $warnings = $report->process_data($data); $this->assertEquals(count($warnings), 1); $studentgrade = grade_grade::fetch(array('itemid' => $forum1->id, '' => $student->id)); $this->assertEquals($studentgrade->finalgrade, $forummax); // Grade below min. Should be pulled up to min. $toosmall = -10.0; $data->grade[$student->id][$forum1->id] = $toosmall; $data->timepageload = time(); $warnings = $report->process_data($data); $this->assertEquals(count($warnings), 1); $studentgrade = grade_grade::fetch(array('itemid' => $forum1->id, '' => $student->id)); $this->assertEquals($studentgrade->finalgrade, 0); // Test unlimited grades so we can give a student a grade about max. $CFG->unlimitedgrades = 1; $data->grade[$student->id][$forum1->id] = $toobig; $data->timepageload = time(); $warnings = $report->process_data($data); $this->assertEquals(count($warnings), 0); $studentgrade = grade_grade::fetch(array('itemid' => $forum1->id, '' => $student->id)); $this->assertEquals($studentgrade->finalgrade, $toobig); }
/** * Initialise the iterator * @return boolean success */ function init() { global $CFG; $this->close(); grade_regrade_final_grades($this->course->id); $course_item = grade_item::fetch_course_item($this->course->id); if ($course_item->needsupdate) { // can not calculate all final grades - sorry return false; } if (strpos($CFG->gradebookroles, ',') === false) { $gradebookroles = " = {$CFG->gradebookroles}"; } else { $gradebookroles = " IN ({$CFG->gradebookroles})"; } $relatedcontexts = get_related_contexts_string(get_context_instance(CONTEXT_COURSE, $this->course->id)); if ($this->groupid) { $groupsql = "INNER JOIN {$CFG->prefix}groups_members gm ON gm.userid = u.id"; $groupwheresql = "AND gm.groupid = {$this->groupid}"; } else { $groupsql = ""; $groupwheresql = ""; } if (empty($this->sortfield1)) { // we must do some sorting even if not specified $ofields = ", u.id AS usrt"; $order = "usrt ASC"; } else { $ofields = ", u.{$this->sortfield1} AS usrt1"; $order = "usrt1 {$this->sortorder1}"; if (!empty($this->sortfield2)) { $ofields .= ", u.{$this->sortfield2} AS usrt2"; $order .= ", usrt2 {$this->sortorder2}"; } if ($this->sortfield1 != 'id' and $this->sortfield2 != 'id') { // user order MUST be the same in both queries, must include the only unique user->id if not already present $ofields .= ", u.id AS usrt"; $order .= ", usrt ASC"; } } $users_sql = "SELECT u.* {$ofields}\n FROM {$CFG->prefix}user u\n INNER JOIN {$CFG->prefix}role_assignments ra ON u.id = ra.userid\n {$groupsql}\n WHERE ra.roleid {$gradebookroles}\n AND ra.contextid {$relatedcontexts}\n {$groupwheresql}\n ORDER BY {$order}"; $this->users_rs = get_recordset_sql($users_sql); if (!empty($this->grade_items)) { $itemids = array_keys($this->grade_items); $itemids = implode(',', $itemids); $grades_sql = "SELECT g.* {$ofields}\n FROM {$CFG->prefix}grade_grades g\n INNER JOIN {$CFG->prefix}user u ON g.userid = u.id\n INNER JOIN {$CFG->prefix}role_assignments ra ON u.id = ra.userid\n {$groupsql}\n WHERE ra.roleid {$gradebookroles}\n AND ra.contextid {$relatedcontexts}\n AND g.itemid IN ({$itemids})\n {$groupwheresql}\n ORDER BY {$order}, g.itemid ASC"; $this->grades_rs = get_recordset_sql($grades_sql); } else { $this->grades_rs = false; } return true; }
public function execute() { global $DB; $TIMELIMITHOURS = 8; $timebound = time() - $TIMELIMITHOURS * 60 * 60; $sql = 'SELECT id, itemid, userid FROM {grade_grades} WHERE locked = 0 AND overridden > 0 AND overridden < ?'; $records = $DB->get_records_sql($sql, array($timebound)); foreach ($records as $record) { $gradeitem = \grade_item::fetch(array('id' => $record->itemid)); $grades = \grade_grade::fetch_users_grades($gradeitem, array($record->userid)); $grades[$record->userid]->set_locked(1); } }
public function test_grade_edit_tree_column_range_get_item_cell() { global $DB, $CFG; $this->resetAfterTest(true); // Make some things we need. $scale = $this->getDataGenerator()->create_scale(); $course = $this->getDataGenerator()->create_course(); $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id)); $modulecontext = context_module::instance($assign->id); // The generator returns a dummy object, lets get the real assign object. $assign = new assign($modulecontext, false, false); $cm = $assign->get_course_module(); // Get range column. $column = grade_edit_tree_column::factory('range'); $gradeitemparams = array('itemtype' => 'mod', 'itemmodule' => $cm->modname, 'iteminstance' => $cm->instance, 'courseid' => $cm->course, 'itemnumber' => 0); // Lets set the grade to something we know. $instance = $assign->get_instance(); $instance->grade = 70; $instance->instance = $instance->id; $assign->update_instance($instance); $gradeitem = grade_item::fetch($gradeitemparams); $cell = $column->get_item_cell($gradeitem, array()); $this->assertEquals(GRADE_TYPE_VALUE, $gradeitem->gradetype); $this->assertEquals(null, $gradeitem->scaleid); $this->assertEquals(70.0, (double) $cell->text, "Grade text is 70", 0.01); // Now change it to a scale. $instance = $assign->get_instance(); $instance->grade = -$scale->id; $instance->instance = $instance->id; $assign->update_instance($instance); $gradeitem = grade_item::fetch($gradeitemparams); $cell = $column->get_item_cell($gradeitem, array()); // Make the expected scale text. $scaleitems = null; $scaleitems = explode(',', $scale->scale); $scalestring = end($scaleitems) . ' (' . count($scaleitems) . ')'; $this->assertEquals(GRADE_TYPE_SCALE, $gradeitem->gradetype); $this->assertEquals($scale->id, $gradeitem->scaleid); $this->assertEquals($scalestring, $cell->text, "Grade text matches scale"); // Now change it to no grade. $instance = $assign->get_instance(); $instance->grade = 0; $instance->instance = $instance->id; $assign->update_instance($instance); $gradeitem = grade_item::fetch($gradeitemparams); $cell = $column->get_item_cell($gradeitem, array()); $this->assertEquals(GRADE_TYPE_TEXT, $gradeitem->gradetype); $this->assertEquals(null, $gradeitem->scaleid); $this->assertEquals(' - ', $cell->text, 'Grade text matches empty value of " - "'); }
function validation($data, $files) { $errors = parent::validation($data, $files); $mform =& $this->_form; // check the calculation formula if ($data['calculation'] != '') { $grade_item = grade_item::fetch(array('id' => $data['id'], 'courseid' => $data['courseid'])); $calculation = calc_formula::unlocalize(stripslashes($data['calculation'])); $result = $grade_item->validate_formula($calculation); if ($result !== true) { $errors['calculation'] = $result; } } return $errors; }
/** * Tests the gradebookservice get grade service. * * @return void */ public function test_get_grade() { global $DB; $callback = 'block_mhaairs_gradebookservice_external::get_grade'; $this->set_user('admin'); // Add mhaairs grade item directly. $params = array('courseid' => $this->course->id, 'itemtype' => 'manual', 'itemmodule' => 'mhaairs', 'iteminstance' => 101, 'itemname' => 'MH Assignment'); $gitem = new \grade_item($params, false); $gitem->insert('mhaairs'); // Add user grade directly. $params = array('itemid' => $gitem->id, 'userid' => $this->student1->id, 'finalgrade' => '95'); $ggrade = new \grade_grade($params, false); $ggrade->insert('mhaairs'); // Service params. $serviceparams = array('source' => 'mhaairs', 'courseid' => $this->course->id, 'itemtype' => 'manual', 'itemmodule' => 'mhaairs', 'iteminstance' => 101, 'itemnumber' => 0, 'grades' => null, 'itemdetails' => null); // Grade details. $grades = array('userid' => 'student1', 'identity_type' => ''); $gradesjson = urlencode(json_encode($grades)); $serviceparams['grades'] = $gradesjson; $result = call_user_func_array($callback, $serviceparams); $this->assertEquals('MH Assignment', $result['item']['itemname']); $this->assertEquals($this->student1->id, $result['grades'][0]['userid']); $this->assertEquals(95, $result['grades'][0]['grade']); }
/** * Prepare to print the course grade. * * @deprecated since iomadcertificate version 2012052501 * @param stdClass $course * @return mixed */ function iomadcertificate_print_course_grade($course) { debugging('iomadcertificate_print_course_grade is deprecated, please use iomadcertificate_get_grade instead. Ideally you should be using iomadcertificate_get_grade in your iomadcertificate type which will either get the course or module grade depending on your iomadcertificate settings.', DEBUG_DEVELOPER); global $USER, $DB; if ($course_item = grade_item::fetch_course_item($course->id)) { $grade = new grade_grade(array('itemid' => $course_item->id, 'userid' => $USER->id)); $course_item->gradetype = GRADE_TYPE_VALUE; $coursegrade = new stdClass(); $coursegrade->points = grade_format_gradevalue($grade->finalgrade, $course_item, true, GRADE_DISPLAY_TYPE_REAL, $decimals = 2); $coursegrade->percentage = grade_format_gradevalue($grade->finalgrade, $course_item, true, GRADE_DISPLAY_TYPE_PERCENTAGE, $decimals = 2); $coursegrade->letter = grade_format_gradevalue($grade->finalgrade, $course_item, true, GRADE_DISPLAY_TYPE_LETTER, $decimals = 0); return $coursegrade; } return false; }
/** * Updates activity completion status. * * @return void */ public static function update_require_specific_grade(\core\event\base $event) { global $DB; $entryuserid = $event->relateduserid; $giid = $event->other['itemid']; if (!($gitem = \grade_item::fetch(array('id' => $giid, 'itemmodule' => 'dataform')))) { return; } $dataformid = $gitem->iteminstance; $df = \mod_dataform_dataform::instance($dataformid); // Currently only completion by require entries. if ($df->completionspecificgrade) { $completion = new \completion_info($df->course); if ($completion->is_enabled($df->cm) != COMPLETION_TRACKING_AUTOMATIC) { return; } $completion->update_state($df->cm, COMPLETION_UNKNOWN, $entryuserid); } }
public function cleanup() { // cleanup any clickers before the test $user_id = iclicker_service::require_user(); $results = iclicker_service::get_registrations_by_user($user_id); if ($results) { echo "cleanup registrations for user: {$user_id} " . PHP_EOL; foreach ($results as $reg) { if ($reg->clicker_id == $this->clicker_id) { iclicker_service::remove_registration($reg->id); echo "cleanup: {$reg->id} " . PHP_EOL; } } } // cleanup the test grades $def_grade_cats = grade_category::fetch_all(array('courseid' => $this->courseid, 'fullname' => iclicker_service::GRADE_CATEGORY_NAME)); $stuff_grade_cats = grade_category::fetch_all(array('courseid' => $this->courseid, 'fullname' => 'stuff')); $grade_cats = $def_grade_cats; if (is_array($def_grade_cats) && is_array($stuff_grade_cats)) { $grade_cats = array_merge($def_grade_cats, $stuff_grade_cats); } else { if (is_array($stuff_grade_cats)) { $grade_cats = $stuff_grade_cats; } } if ($grade_cats) { foreach ($grade_cats as $cat) { $grade_items = grade_item::fetch_all(array('courseid' => $this->courseid, 'categoryid' => $cat->id)); if ($grade_items) { foreach ($grade_items as $item) { $grades = grade_grade::fetch_all(array('itemid' => $item->id)); if ($grades) { foreach ($grades as $grade) { $grade->delete("cleanup"); } } $item->delete("cleanup"); } } $cat->delete("cleanup"); } } }
function validation($data) { $errors = array(); $mform =& $this->_form; // check the calculation formula if ($data['calculation'] != '') { $grade_item = grade_item::fetch(array('id' => $data['id'], 'courseid' => $data['courseid'])); $calculation = calc_formula::unlocalize(stripslashes($data['calculation'])); $result = $grade_item->validate_formula($calculation); if ($result !== true) { $errors['calculation'] = $result; } } if (0 == count($errors)) { return true; } else { return $errors; } }
/** * Sets up the table_log parameters. * * @param string $uniqueid unique id of table. * @param \context_course $context Context of the report. * @param \moodle_url $url url of the page where this table would be displayed. * @param array $filters options are: * userids : limit to specific users (default: none) * itemid : limit to specific grade item (default: all) * grader : limit to specific graders (default: all) * datefrom : start of date range * datetill : end of date range * revisedonly : only show revised grades (default: false) * format : page | csv | excel (default: page) * @param string $download Represents download format, pass '' no download at this time. * @param int $page The current page being displayed. * @param int $perpage Number of rules to display per page. */ public function __construct($uniqueid, \context_course $context, $url, $filters = array(), $download = '', $page = 0, $perpage = 100) { parent::__construct($uniqueid); $this->set_attribute('class', 'gradereport_history generaltable generalbox'); // Set protected properties. $this->context = $context; $this->courseid = $this->context->instanceid; $this->pagesize = $perpage; $this->page = $page; $this->filters = (object) $filters; $this->gradeitems = \grade_item::fetch_all(array('courseid' => $this->courseid)); $this->cms = get_fast_modinfo($this->courseid); $this->useridfield = 'userid'; // Define columns in the table. $this->define_table_columns(); // Define configs. $this->define_table_configs($url); // Set download status. $this->is_downloading($download, get_string('exportfilename', 'gradereport_history')); }
/** * Adds a grade category and moves the specified item into it. * Uses locks to prevent race conditions (see MDL-37055). */ public function execute() { $customdata = $this->get_custom_data(); // Get lock timeout. $timeout = 5; // A namespace for the locks. $locktype = 'block_mhaairs_add_category'; // Resource key - course id and category name. $resource = "course: {$customdata->courseid}; catname: {$customdata->catname}"; // Get an instance of the currently configured lock_factory. $lockfactory = \core\lock\lock_config::get_lock_factory($locktype); // Open a lock. $lock = $lockfactory->get_lock($resource, $timeout); // Add the category. $catparams = array('fullname' => $customdata->catname, 'courseid' => $customdata->courseid); if (!($category = \grade_category::fetch($catparams))) { // If the category does not exist we create it. $gradeaggregation = get_config('core', 'grade_aggregation'); if ($gradeaggregation === false) { $gradeaggregation = GRADE_AGGREGATE_WEIGHTED_MEAN2; } // Parent category is automatically added(created) during insert. $catparams['hidden'] = false; $catparams['aggregation'] = $gradeaggregation; try { $category = new \grade_category($catparams, false); $category->id = $category->insert(); } catch (Exception $e) { // Must release the locks. $lock->release(); // Rethrow to reschedule task. throw $e; } } // Release locks. $lock->release(); // Add the item to the category. $gitem = \grade_item::fetch(array('id' => $customdata->itemid)); $gitem->categoryid = $category->id; $gitem->update(); }
/** * Tests the event details. */ public function test_event() { global $CFG; require_once "{$CFG->libdir}/gradelib.php"; $this->resetAfterTest(); $course = $this->getDataGenerator()->create_course(); $user = $this->getDataGenerator()->create_user(); $quiz = $this->getDataGenerator()->create_module('quiz', array('course' => $course->id)); // Create a grade item for the quiz. $grade = array(); $grade['userid'] = $user->id; $grade['rawgrade'] = 50; grade_update('mod/quiz', $course->id, 'mod', 'quiz', $quiz->id, 0, $grade); // Get the grade item and override it. $gradeitem = grade_item::fetch(array('itemtype' => 'mod', 'itemmodule' => 'quiz', 'iteminstance' => $quiz->id, 'courseid' => $course->id)); $gradeitem->update_final_grade($user->id, 10, 'gradebook'); // Get the grade_grade object. $gradegrade = new grade_grade(array('userid' => $user->id, 'itemid' => $gradeitem->id), true); $gradegrade->grade_item = $gradeitem; // Trigger the event. $sink = $this->redirectEvents(); course_delete_module($quiz->cmid); $events = $sink->get_events(); $event = reset($events); $sink->close(); // Check the event details are correct. $grade = $event->get_grade(); $this->assertInstanceOf('grade_grade', $grade); $this->assertInstanceOf('\\core\\event\\grade_deleted', $event); $this->assertEquals(context_course::instance($course->id), $event->get_context()); $this->assertSame($event->objecttable, 'grade_grades'); $this->assertEquals($event->objectid, $gradegrade->id); $this->assertEquals($event->other['itemid'], $gradeitem->id); $this->assertTrue($event->other['overridden']); $this->assertEquals(10, $event->other['finalgrade']); $this->assertEventContextNotUsed($event); $this->assertEquals($gradegrade->id, $grade->id); }
/** * Constructor should set up all the private variables ready to be pulled * @param object $course * @param int $groupid id of selected group, 0 means all * @param string $itemlist comma separated list of item ids, empty means all * @param boolean $export_feedback * @param boolean $export_letters * @note Exporting as letters will lead to data loss if that exported set it re-imported. */ function grade_export($course, $groupid = 0, $itemlist = '', $export_feedback = false, $export_letters = false) { $this->course = $course; $this->groupid = $groupid; $this->grade_items = grade_item::fetch_all(array('courseid' => $this->course->id)); $this->columns = array(); if (!empty($itemlist)) { $itemids = explode(',', $itemlist); // remove items that are not requested foreach ($itemids as $itemid) { if (array_key_exists($itemid, $this->grade_items)) { $this->columns[$itemid] =& $this->grade_items[$itemid]; } } } else { foreach ($this->grade_items as $itemid => $unused) { $this->columns[$itemid] =& $this->grade_items[$itemid]; } } $this->export_letters = $export_letters; $this->export_feedback = $export_feedback; $this->userkey = ''; $this->previewrows = false; }
public function __construct() { global $DB; parent::__construct(get_string('gradedistributiongroupbar', 'gradereport_visual')); $this->layout = visualization::LAYOUT_AXIS; $this->layoutsettings = array('false', 'true'); $this->nodeshape = visualization::SHAPE_VERTICAL_BAR; $this->xaxis = 'grade'; $this->yaxis = 'students'; $this->xaxislabelformat = '0\\%'; $this->xaxisxoffset = -27; $this->xaxislabel = get_string('grade', 'gradereport_visual'); if ($this->percent) { $this->yaxislabelformat = '0\\%'; $this->yaxislabel = get_string('percentstudents', 'gradereport_visual'); } else { $this->yaxislabel = get_string('numberstudents', 'gradereport_visual'); } $this->title = get_string('gradedistribution:title', 'gradereport_visual'); $this->capability = 'gradereport/visual:vis:grade_distribution_group_bar'; $courseid = required_param('id'); $options = array(); $items = grade_item::fetch_all(array('courseid' => $courseid)); foreach ($items as $item) { if (count($item->get_final()) > 0) { $options[$item->id] = grade_report_visual::truncate($item->get_name()); } } $options['ai'] = 'All Items'; $this->selector = new selector('item', $options, 'ai'); $this->selectors = array($this->selector); $this->colorencoder = new encoder(encoder::ENCODER_COLOR, 'group'); $this->encoders = array($this->colorencoder); $this->grouplegend = new legend($this->colorencoder); $this->legends = array($this->grouplegend); }
// 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(); $recreatetree = true; // Grade item checkbox inputs. } elseif (preg_match('/^(weightoverride)_([0-9]+)$/', $key, $matches)) { $param = $matches[1]; $aid = $matches[2]; $value = clean_param($value, PARAM_BOOL); $grade_item = grade_item::fetch(array('id' => $aid, 'courseid' => $courseid)); $grade_item->{$param} = $value; $grade_item->update(); $recreatetree = true; } } $originalweights = grade_helper::fetch_all_natural_weights_for_course($courseid); grade_regrade_final_grades($courseid); $alteredweights = grade_helper::fetch_all_natural_weights_for_course($courseid); if (array_diff($originalweights, $alteredweights)) { $normalisationmessage = get_string('weightsadjusted', 'grades'); } } print_grade_page_head($courseid, 'settings', 'setup', get_string('categoriesanditems', 'grades')); // Print Table of categories and items echo $OUTPUT->box_start('gradetreebox generalbox');
function import_xml_grades($text, $course, &$error) { global $USER; $importcode = get_new_importcode(); $status = true; $content = xmlize($text); if (!empty($content['results']['#']['result'])) { $results = $content['results']['#']['result']; foreach ($results as $i => $result) { $gradeidnumber = $result['#']['assignment'][0]['#']; if (!($grade_items = grade_item::fetch_all(array('idnumber' => $gradeidnumber, 'courseid' => $course->id)))) { // gradeitem does not exist // no data in temp table so far, abort $status = false; $error = get_string('errincorrectgradeidnumber', 'gradeimport_xml', $gradeidnumber); break; } else { if (count($grade_items) != 1) { $status = false; $error = get_string('errduplicategradeidnumber', 'gradeimport_xml', $gradeidnumber); break; } else { $grade_item = reset($grade_items); } } // grade item locked, abort if ($grade_item->is_locked()) { $status = false; $error = get_string('gradeitemlocked', 'grades'); break; } // check if user exist and convert idnumber to user id $useridnumber = $result['#']['student'][0]['#']; if (!($user = get_record('user', 'idnumber', addslashes($useridnumber)))) { // no user found, abort $status = false; $error = get_string('errincorrectuseridnumber', 'gradeimport_xml', $useridnumber); break; } // check if grade_grade is locked and if so, abort if ($grade_grade = new grade_grade(array('itemid' => $grade_item->id, 'userid' => $user->id))) { $grade_grade->grade_item =& $grade_item; if ($grade_grade->is_locked()) { // individual grade locked, abort $status = false; $error = get_string('gradegradeslocked', 'grades'); break; } } $newgrade = new object(); $newgrade->itemid = $grade_item->id; $newgrade->userid = $user->id; $newgrade->importcode = $importcode; $newgrade->importer = $USER->id; // check grade value exists and is a numeric grade if (isset($result['#']['score'][0]['#'])) { if (is_numeric($result['#']['score'][0]['#'])) { $newgrade->finalgrade = $result['#']['score'][0]['#']; } else { $status = false; $error = get_string('badgrade', 'grades'); break; } } else { $newgrade->finalgrade = NULL; } // check grade feedback exists if (isset($result['#']['feedback'][0]['#'])) { $newgrade->feedback = $result['#']['feedback'][0]['#']; } else { $newgrade->feedback = NULL; } // insert this grade into a temp table if (!insert_record('grade_import_values', addslashes_recursive($newgrade))) { $status = false; // could not insert into temp table $error = get_string('importfailed', 'grades'); break; } } } else { // no results section found in xml, // assuming bad format, abort import $status = false; $error = get_string('errbadxmlformat', 'gradeimport_xml'); } if ($status) { return $importcode; } else { import_cleanup($importcode); return false; } }
function definition_after_data() { global $CFG, $COURSE; $mform =& $this->_form; if ($id = $mform->getElementValue('id')) { $grade_item = grade_item::fetch(array('id' => $id)); //remove the aggregation coef element if not needed if ($grade_item->is_course_item()) { if ($mform->elementExists('parentcategory')) { $mform->removeElement('parentcategory'); } if ($mform->elementExists('aggregationcoef')) { $mform->removeElement('aggregationcoef'); } } else { // if we wanted to change parent of existing item - we would have to verify there are no circular references in parents!!! if ($mform->elementExists('parentcategory')) { $mform->hardFreeze('parentcategory'); } if ($grade_item->is_category_item()) { $category = $grade_item->get_item_category(); $parent_category = $category->get_parent_category(); } else { $parent_category = $grade_item->get_parent_category(); } $parent_category->apply_forced_settings(); if (!$parent_category->is_aggregationcoef_used() or $parent_category->aggregation == GRADE_AGGREGATE_SUM) { if ($mform->elementExists('aggregationcoef')) { $mform->removeElement('aggregationcoef'); } } else { //fix label if needed $agg_el =& $mform->getElement('aggregationcoef'); $aggcoef = ''; if ($parent_category->aggregation == GRADE_AGGREGATE_WEIGHTED_MEAN) { $aggcoef = 'aggregationcoefweight'; } else { if ($parent_category->aggregation == GRADE_AGGREGATE_WEIGHTED_MEAN2) { $aggcoef = 'aggregationcoefextrasum'; } else { if ($parent_category->aggregation == GRADE_AGGREGATE_EXTRACREDIT_MEAN) { $aggcoef = 'aggregationcoefextra'; } else { if ($parent_category->aggregation == GRADE_AGGREGATE_SUM) { $aggcoef = 'aggregationcoefextrasum'; } } } } if ($aggcoef !== '') { $agg_el->setLabel(get_string($aggcoef, 'grades')); $mform->setHelpButton('aggregationcoef', array($aggcoef, get_string($aggcoef, 'grades'), 'grade')); } } } } // no parent header for course category if (!$mform->elementExists('aggregationcoef') and !$mform->elementExists('parentcategory')) { $mform->removeElement('headerparent'); } }
/** * Initialise the iterator * * @return boolean success */ public function init() { global $CFG, $DB; $this->close(); export_verify_grades($this->course->id); $course_item = grade_item::fetch_course_item($this->course->id); if ($course_item->needsupdate) { // Can not calculate all final grades - sorry. return false; } $coursecontext = context_course::instance($this->course->id); list($relatedctxsql, $relatedctxparams) = $DB->get_in_or_equal($coursecontext->get_parent_context_ids(true), SQL_PARAMS_NAMED, 'relatedctx'); list($gradebookroles_sql, $params) = $DB->get_in_or_equal(explode(',', $CFG->gradebookroles), SQL_PARAMS_NAMED, 'grbr'); list($enrolledsql, $enrolledparams) = get_enrolled_sql($coursecontext, '', 0, $this->onlyactive); $params = array_merge($params, $enrolledparams, $relatedctxparams); if ($this->groupid) { $groupsql = "INNER JOIN {groups_members} gm ON gm.userid = u.id"; $groupwheresql = "AND gm.groupid = :groupid"; // $params contents: gradebookroles $params['groupid'] = $this->groupid; } else { $groupsql = ""; $groupwheresql = ""; } if (empty($this->sortfield1)) { // We must do some sorting even if not specified. $ofields = ", u.id AS usrt"; $order = "usrt ASC"; } else { $ofields = ", u.{$this->sortfield1} AS usrt1"; $order = "usrt1 {$this->sortorder1}"; if (!empty($this->sortfield2)) { $ofields .= ", u.{$this->sortfield2} AS usrt2"; $order .= ", usrt2 {$this->sortorder2}"; } if ($this->sortfield1 != 'id' and $this->sortfield2 != 'id') { // User order MUST be the same in both queries, // must include the only unique user->id if not already present. $ofields .= ", u.id AS usrt"; $order .= ", usrt ASC"; } } $userfields = 'u.*'; $customfieldssql = ''; if ($this->allowusercustomfields && !empty($CFG->grade_export_customprofilefields)) { $customfieldscount = 0; $customfieldsarray = grade_helper::get_user_profile_fields($this->course->id, $this->allowusercustomfields); foreach ($customfieldsarray as $field) { if (!empty($field->customid)) { $customfieldssql .= "\n LEFT JOIN (SELECT * FROM {user_info_data}\n WHERE fieldid = :cf{$customfieldscount}) cf{$customfieldscount}\n ON u.id = cf{$customfieldscount}.userid"; $userfields .= ", cf{$customfieldscount}.data AS customfield_{$field->shortname}"; $params['cf' . $customfieldscount] = $field->customid; $customfieldscount++; } } } $users_sql = "SELECT {$userfields} {$ofields}\n FROM {user} u\n JOIN ({$enrolledsql}) je ON je.id = u.id\n {$groupsql} {$customfieldssql}\n JOIN (\n SELECT DISTINCT ra.userid\n FROM {role_assignments} ra\n WHERE ra.roleid {$gradebookroles_sql}\n AND ra.contextid {$relatedctxsql}\n ) rainner ON rainner.userid = u.id\n WHERE u.deleted = 0\n {$groupwheresql}\n ORDER BY {$order}"; $this->users_rs = $DB->get_recordset_sql($users_sql, $params); if (!$this->onlyactive) { $context = context_course::instance($this->course->id); $this->suspendedusers = get_suspended_userids($context); } else { $this->suspendedusers = array(); } if (!empty($this->grade_items)) { $itemids = array_keys($this->grade_items); list($itemidsql, $grades_params) = $DB->get_in_or_equal($itemids, SQL_PARAMS_NAMED, 'items'); $params = array_merge($params, $grades_params); $grades_sql = "SELECT g.* {$ofields}\n FROM {grade_grades} g\n JOIN {user} u ON g.userid = u.id\n JOIN ({$enrolledsql}) je ON je.id = u.id\n {$groupsql}\n JOIN (\n SELECT DISTINCT ra.userid\n FROM {role_assignments} ra\n WHERE ra.roleid {$gradebookroles_sql}\n AND ra.contextid {$relatedctxsql}\n ) rainner ON rainner.userid = u.id\n WHERE u.deleted = 0\n AND g.itemid {$itemidsql}\n {$groupwheresql}\n ORDER BY {$order}, g.itemid ASC"; $this->grades_rs = $DB->get_recordset_sql($grades_sql, $params); } else { $this->grades_rs = false; } return true; }
public function after_restore() { // Fix grade item's sortorder after restore, as it might have duplicates. $courseid = $this->get_task()->get_courseid(); grade_item::fix_duplicate_sortorder($courseid); }