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);
     }
 }
 /**
  * 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();
     $coursecontext = context_course::instance($course->id);
     // 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, $coursecontext);
     $testgrade = 60.0;
     $data = new stdClass();
     $data->id = $course->id;
     $data->report = 'grader';
     $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;
     $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;
     $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;
     $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);
 }
 /**
  * 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']);
 }
예제 #4
0
 public function test_task_timefilter()
 {
     $task = new \local_gradelock\task\lock_grades();
     $grade_grade = new grade_grade();
     $grade_grade->itemid = $this->grade_items[0]->id;
     $grade_grade->userid = 10;
     $grade_grade->rawgrade = 88;
     $grade_grade->rawgrademax = 110;
     $grade_grade->rawgrademin = 18;
     $grade_grade->load_grade_item();
     $grade_grade->insert();
     $grade_grade->grade_item->update_final_grade($this->user[0]->id, 100, 'gradebook', '', FORMAT_MOODLE);
     $grade_grade->update();
     $task->execute();
     $grade_grade = grade_grade::fetch(array('userid' => $this->user[0]->id, 'itemid' => $this->grade_items[0]->id));
     $this->assertFalse($grade_grade->is_locked());
 }
 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");
         }
     }
 }
예제 #6
0
 /**
  * Parses the array in search of a given eid and returns a element object with
  * information about the element it has found.
  * @param int $eid Gradetree Element ID
  * @return object element
  */
 public function locate_element($eid)
 {
     // it is a grade - construct a new object
     if (strpos($eid, 'n') === 0) {
         if (!preg_match('/n(\\d+)u(\\d+)/', $eid, $matches)) {
             return null;
         }
         $itemid = $matches[1];
         $userid = $matches[2];
         //extra security check - the grade item must be in this tree
         if (!($item_el = $this->locate_element('i' . $itemid))) {
             return null;
         }
         // $gradea->id may be null - means does not exist yet
         $grade = new grade_grade(array('itemid' => $itemid, 'userid' => $userid));
         $grade->grade_item =& $item_el['object'];
         // this may speedup grade_grade methods!
         return array('eid' => 'n' . $itemid . 'u' . $userid, 'object' => $grade, 'type' => 'grade');
     } else {
         if (strpos($eid, 'g') === 0) {
             $id = (int) substr($eid, 1);
             if (!($grade = grade_grade::fetch(array('id' => $id)))) {
                 return null;
             }
             //extra security check - the grade item must be in this tree
             if (!($item_el = $this->locate_element('i' . $grade->itemid))) {
                 return null;
             }
             $grade->grade_item =& $item_el['object'];
             // this may speedup grade_grade methods!
             return array('eid' => 'g' . $id, 'object' => $grade, 'type' => 'grade');
         }
     }
     // it is a category or item
     foreach ($this->levels as $row) {
         foreach ($row as $element) {
             if ($element['type'] == 'filler') {
                 continue;
             }
             if ($element['eid'] == $eid) {
                 return $element;
             }
         }
     }
     return null;
 }
예제 #7
0
 /**
  * This function is called after the table has been built and the aggregationhints
  * have been collected. We need this info to walk up the list of parents of each
  * grade_item.
  *
  * @param $element - An array containing the table data for the current row.
  */
 public function fill_contributions_column($element)
 {
     // Recursively iterate through all child elements.
     if (isset($element['children'])) {
         foreach ($element['children'] as $key => $child) {
             $this->fill_contributions_column($element['children'][$key]);
         }
     } else {
         if ($element['type'] == 'item') {
             // This is a grade item (We don't do this for categories or we would double count).
             $grade_object = $element['object'];
             $itemid = $grade_object->id;
             // Ignore anything with no hint - e.g. a hidden row.
             if (isset($this->aggregationhints[$itemid])) {
                 // Normalise the gradeval.
                 $gradecat = $grade_object->load_parent_category();
                 if ($gradecat->aggregation == GRADE_AGGREGATE_SUM) {
                     // Natural aggregation/Sum of grades does not consider the mingrade, cannot traditionnally normalise it.
                     $graderange = $this->aggregationhints[$itemid]['grademax'];
                     if ($graderange != 0) {
                         $gradeval = $this->aggregationhints[$itemid]['grade'] / $graderange;
                     } else {
                         $gradeval = 0;
                     }
                 } else {
                     $gradeval = grade_grade::standardise_score($this->aggregationhints[$itemid]['grade'], $this->aggregationhints[$itemid]['grademin'], $this->aggregationhints[$itemid]['grademax'], 0, 1);
                 }
                 // Multiply the normalised value by the weight
                 // of all the categories higher in the tree.
                 $parent = null;
                 do {
                     if (!is_null($this->aggregationhints[$itemid]['weight'])) {
                         $gradeval *= $this->aggregationhints[$itemid]['weight'];
                     } else {
                         if (empty($parent)) {
                             // If we are in the first loop, and the weight is null, then we cannot calculate the contribution.
                             $gradeval = null;
                             break;
                         }
                     }
                     // The second part of this if is to prevent infinite loops
                     // in case of crazy data.
                     if (isset($this->aggregationhints[$itemid]['parent']) && $this->aggregationhints[$itemid]['parent'] != $itemid) {
                         $parent = $this->aggregationhints[$itemid]['parent'];
                         $itemid = $parent;
                     } else {
                         // We are at the top of the tree.
                         $parent = false;
                     }
                 } while ($parent);
                 // Finally multiply by the course grademax.
                 if (!is_null($gradeval)) {
                     // Convert to percent.
                     $gradeval *= 100;
                 }
                 // Now we need to loop through the "built" table data and update the
                 // contributions column for the current row.
                 $header_row = "row_{$grade_object->id}_{$this->user->id}";
                 foreach ($this->tabledata as $key => $row) {
                     if (isset($row['itemname']) && $row['itemname']['id'] == $header_row) {
                         // Found it - update the column.
                         $content = '-';
                         if (!is_null($gradeval)) {
                             $decimals = $grade_object->get_decimals();
                             $content = format_float($gradeval, $decimals, true) . ' %';
                         }
                         $this->tabledata[$key]['contributiontocoursetotal']['content'] = $content;
                         break;
                     }
                 }
             }
         }
     }
 }
예제 #8
0
 /**
  * Internal function for category grades summing
  *
  * @param grade_grade $grade The grade item
  * @param float $oldfinalgrade Old Final grade
  * @param array $items Grade items
  * @param array $grade_values Grade values
  * @param array $excluded Excluded
  */
 private function sum_grades(&$grade, $oldfinalgrade, $items, $grade_values, $excluded)
 {
     if (empty($items)) {
         return null;
     }
     // ungraded and excluded items are not used in aggregation
     foreach ($grade_values as $itemid => $v) {
         if (is_null($v)) {
             unset($grade_values[$itemid]);
         } else {
             if (in_array($itemid, $excluded)) {
                 unset($grade_values[$itemid]);
             }
         }
     }
     // use 0 if grade missing, droplow used and aggregating all items
     if (!$this->aggregateonlygraded and !empty($this->droplow)) {
         foreach ($items as $itemid => $value) {
             if (!isset($grade_values[$itemid]) and !in_array($itemid, $excluded)) {
                 $grade_values[$itemid] = 0;
             }
         }
     }
     $this->apply_limit_rules($grade_values, $items);
     $sum = array_sum($grade_values);
     $grade->finalgrade = $this->grade_item->bounded_grade($sum);
     // update in db if changed
     if (grade_floats_different($grade->finalgrade, $oldfinalgrade)) {
         $grade->update('aggregation');
     }
     return;
 }
예제 #9
0
    protected function process_grade_grade($data) {
        $data = (object)($data);

        unset($data->id);
        $data->itemid = $this->get_new_parentid('grade_item');
        $data->userid = $this->get_mappingid('user', $data->userid);
        $data->usermodified = $this->get_mappingid('user', $data->usermodified);
        $data->rawscaleid = $this->get_mappingid('scale', $data->rawscaleid);
        // TODO: Ask, all the rest of locktime/exported... work with time... to be rolled?
        $data->overridden = $this->apply_date_offset($data->overridden);

        $grade = new grade_grade($data, false);
        $grade->insert('restore');
        // no need to save any grade_grade mapping
    }
예제 #10
0
 /**
  * If the requirements are met - reopen the submission for another attempt.
  * Only call this function when grading the latest attempt.
  *
  * @param int $userid The userid.
  * @param stdClass $submission The submission (may be a group submission).
  * @param bool $addattempt - True if the "allow another attempt" checkbox was checked.
  * @return bool - true if another attempt was added.
  */
 protected function reopen_submission_if_required($userid, $submission, $addattempt)
 {
     $instance = $this->get_instance();
     $maxattemptsreached = !empty($submission) && $submission->attemptnumber >= $instance->maxattempts - 1 && $instance->maxattempts != ASSIGN_UNLIMITED_ATTEMPTS;
     $shouldreopen = false;
     if ($instance->attemptreopenmethod == ASSIGN_ATTEMPT_REOPEN_METHOD_UNTILPASS) {
         // Check the gradetopass from the gradebook.
         $gradeitem = $this->get_grade_item();
         if ($gradeitem) {
             $gradegrade = grade_grade::fetch(array('userid' => $userid, 'itemid' => $gradeitem->id));
             // Do not reopen if is_passed returns null, e.g. if there is no pass criterion set.
             if ($gradegrade && $gradegrade->is_passed() === false) {
                 $shouldreopen = true;
             }
         }
     }
     if ($instance->attemptreopenmethod == ASSIGN_ATTEMPT_REOPEN_METHOD_MANUAL && !empty($addattempt)) {
         $shouldreopen = true;
     }
     if ($shouldreopen && !$maxattemptsreached) {
         $this->add_attempt($userid);
         return true;
     }
     return false;
 }
예제 #11
0
 /**
  * Tests grade_report::blank_hidden_total_and_adjust_bounds()
  */
 public function test_blank_hidden_total_and_adjust_bounds()
 {
     global $DB;
     $this->resetAfterTest(true);
     $student = $this->getDataGenerator()->create_user();
     $this->setUser($student);
     // Create a course and two activities.
     // One activity will be hidden.
     $course = $this->getDataGenerator()->create_course();
     $coursegradeitem = grade_item::fetch_course_item($course->id);
     $coursecontext = context_course::instance($course->id);
     $data = $this->getDataGenerator()->create_module('data', array('assessed' => 1, 'scale' => 100, 'course' => $course->id));
     $datacm = get_coursemodule_from_id('data', $data->cmid);
     $forum = $this->getDataGenerator()->create_module('forum', array('assessed' => 1, 'scale' => 100, 'course' => $course->id));
     $forumcm = get_coursemodule_from_id('forum', $forum->cmid);
     // Insert student grades for the two activities.
     $gi = grade_item::fetch(array('itemtype' => 'mod', 'itemmodule' => 'data', 'iteminstance' => $data->id, 'courseid' => $course->id));
     $datagrade = 50;
     $grade_grade = new grade_grade();
     $grade_grade->itemid = $gi->id;
     $grade_grade->userid = $student->id;
     $grade_grade->rawgrade = $datagrade;
     $grade_grade->finalgrade = $datagrade;
     $grade_grade->rawgrademax = 100;
     $grade_grade->rawgrademin = 0;
     $grade_grade->timecreated = time();
     $grade_grade->timemodified = time();
     $grade_grade->insert();
     $gi = grade_item::fetch(array('itemtype' => 'mod', 'itemmodule' => 'forum', 'iteminstance' => $forum->id, 'courseid' => $course->id));
     $forumgrade = 70;
     $grade_grade = new grade_grade();
     $grade_grade->itemid = $gi->id;
     $grade_grade->userid = $student->id;
     $grade_grade->rawgrade = $forumgrade;
     $grade_grade->finalgrade = $forumgrade;
     $grade_grade->rawgrademax = 100;
     $grade_grade->rawgrademin = 0;
     $grade_grade->timecreated = time();
     $grade_grade->timemodified = time();
     $grade_grade->insert();
     // Hide the database activity.
     set_coursemodule_visible($datacm->id, 0);
     $gpr = new grade_plugin_return(array('type' => 'report', 'courseid' => $course->id));
     $report = new grade_report_test($course->id, $gpr, $coursecontext, $student);
     // Should return the supplied student total grade regardless of hiding.
     $report->showtotalsifcontainhidden = array($course->id => GRADE_REPORT_SHOW_REAL_TOTAL_IF_CONTAINS_HIDDEN);
     $result = $report->blank_hidden_total_and_adjust_bounds($course->id, $coursegradeitem, $datagrade + $forumgrade);
     $this->assertEquals(array('grade' => $datagrade + $forumgrade, 'grademax' => $coursegradeitem->grademax, 'grademin' => $coursegradeitem->grademin, 'aggregationstatus' => 'unknown', 'aggregationweight' => null), $result);
     // Should blank the student total as course grade depends on a hidden item.
     $report->showtotalsifcontainhidden = array($course->id => GRADE_REPORT_HIDE_TOTAL_IF_CONTAINS_HIDDEN);
     $result = $report->blank_hidden_total_and_adjust_bounds($course->id, $coursegradeitem, $datagrade + $forumgrade);
     $this->assertEquals(array('grade' => null, 'grademax' => $coursegradeitem->grademax, 'grademin' => $coursegradeitem->grademin, 'aggregationstatus' => 'unknown', 'aggregationweight' => null), $result);
     // Should return the course total minus the hidden database activity grade.
     $report->showtotalsifcontainhidden = array($course->id => GRADE_REPORT_SHOW_TOTAL_IF_CONTAINS_HIDDEN);
     $result = $report->blank_hidden_total_and_adjust_bounds($course->id, $coursegradeitem, $datagrade + $forumgrade);
     $this->assertEquals(array('grade' => floatval($forumgrade), 'grademax' => $coursegradeitem->grademax, 'grademin' => $coursegradeitem->grademin, 'aggregationstatus' => 'unknown', 'aggregationweight' => null), $result);
     // Note: we cannot simply hide modules and call $report->blank_hidden_total() again.
     // It stores grades in a static variable so $report->blank_hidden_total() will return incorrect totals
     // In practice this isn't a problem. Grade visibility isn't altered mid-request outside of the unit tests.
     // Add a second course to test:
     // 1) How a course with no visible activities behaves.
     // 2) That $report->blank_hidden_total() correctly moves on to the new course.
     $course = $this->getDataGenerator()->create_course();
     $coursegradeitem = grade_item::fetch_course_item($course->id);
     $coursecontext = context_course::instance($course->id);
     $data = $this->getDataGenerator()->create_module('data', array('assessed' => 1, 'scale' => 100, 'course' => $course->id));
     $datacm = get_coursemodule_from_id('data', $data->cmid);
     $forum = $this->getDataGenerator()->create_module('forum', array('assessed' => 1, 'scale' => 100, 'course' => $course->id));
     $forumcm = get_coursemodule_from_id('forum', $forum->cmid);
     $gi = grade_item::fetch(array('itemtype' => 'mod', 'itemmodule' => 'data', 'iteminstance' => $data->id, 'courseid' => $course->id));
     $datagrade = 50;
     $grade_grade = new grade_grade();
     $grade_grade->itemid = $gi->id;
     $grade_grade->userid = $student->id;
     $grade_grade->rawgrade = $datagrade;
     $grade_grade->finalgrade = $datagrade;
     $grade_grade->rawgrademax = 100;
     $grade_grade->rawgrademin = 0;
     $grade_grade->timecreated = time();
     $grade_grade->timemodified = time();
     $grade_grade->insert();
     $gi = grade_item::fetch(array('itemtype' => 'mod', 'itemmodule' => 'forum', 'iteminstance' => $forum->id, 'courseid' => $course->id));
     $forumgrade = 70;
     $grade_grade = new grade_grade();
     $grade_grade->itemid = $gi->id;
     $grade_grade->userid = $student->id;
     $grade_grade->rawgrade = $forumgrade;
     $grade_grade->finalgrade = $forumgrade;
     $grade_grade->rawgrademax = 100;
     $grade_grade->rawgrademin = 0;
     $grade_grade->timecreated = time();
     $grade_grade->timemodified = time();
     $grade_grade->insert();
     // Hide both activities.
     set_coursemodule_visible($datacm->id, 0);
     set_coursemodule_visible($forumcm->id, 0);
     $gpr = new grade_plugin_return(array('type' => 'report', 'courseid' => $course->id));
     $report = new grade_report_test($course->id, $gpr, $coursecontext, $student);
     // Should return the supplied student total grade regardless of hiding.
     $report->showtotalsifcontainhidden = array($course->id => GRADE_REPORT_SHOW_REAL_TOTAL_IF_CONTAINS_HIDDEN);
     $result = $report->blank_hidden_total_and_adjust_bounds($course->id, $coursegradeitem, $datagrade + $forumgrade);
     $this->assertEquals(array('grade' => $datagrade + $forumgrade, 'grademax' => $coursegradeitem->grademax, 'grademin' => $coursegradeitem->grademin, 'aggregationstatus' => 'unknown', 'aggregationweight' => null), $result);
     // Should blank the student total as course grade depends on a hidden item.
     $report->showtotalsifcontainhidden = array($course->id => GRADE_REPORT_HIDE_TOTAL_IF_CONTAINS_HIDDEN);
     $result = $report->blank_hidden_total_and_adjust_bounds($course->id, $coursegradeitem, $datagrade + $forumgrade);
     $this->assertEquals(array('grade' => null, 'grademax' => $coursegradeitem->grademax, 'grademin' => $coursegradeitem->grademin, 'aggregationstatus' => 'unknown', 'aggregationweight' => null), $result);
     // Should return the course total minus the hidden activity grades.
     // They are both hidden so should return null.
     $report->showtotalsifcontainhidden = array($course->id => GRADE_REPORT_SHOW_TOTAL_IF_CONTAINS_HIDDEN);
     $result = $report->blank_hidden_total_and_adjust_bounds($course->id, $coursegradeitem, $datagrade + $forumgrade);
     $this->assertEquals(array('grade' => null, 'grademax' => $coursegradeitem->grademax, 'grademin' => $coursegradeitem->grademin, 'aggregationstatus' => 'unknown', 'aggregationweight' => null), $result);
 }
예제 #12
0
 /**
  * Return array of grade item ids that are either hidden or indirectly depend
  * on hidden grades, excluded grades are not returned.
  * THIS IS A REALLY BIG HACK! to be replaced by conditional aggregation of hidden grades in 2.0
  *
  * @param array $grade_grades all course grades of one user, & used for better internal caching
  * @param array $grade_items array of grade items, & used for better internal caching
  * @return array This is an array of 3 arrays:
  *      unknown => list of item ids that may be affected by hiding (with the calculated grade as the value)
  *      altered => list of item ids that are definitely affected by hiding (with the calculated grade as the value)
  *      alteredgrademax => for each item in altered or unknown, the new value of the grademax
  *      alteredgrademin => for each item in altered or unknown, the new value of the grademin
  *      alteredgradestatus => for each item with a modified status - the value of the new status
  *      alteredgradeweight => for each item with a modified weight - the value of the new weight
  */
 public static function get_hiding_affected(&$grade_grades, &$grade_items)
 {
     global $CFG;
     if (count($grade_grades) !== count($grade_items)) {
         print_error('invalidarraysize', 'debug', '', 'grade_grade::get_hiding_affected()!');
     }
     $dependson = array();
     $todo = array();
     $unknown = array();
     // can not find altered
     $altered = array();
     // altered grades
     $alteredgrademax = array();
     // Altered grade max values.
     $alteredgrademin = array();
     // Altered grade min values.
     $alteredaggregationstatus = array();
     // Altered aggregation status.
     $alteredaggregationweight = array();
     // Altered aggregation weight.
     $dependencydepth = array();
     $hiddenfound = false;
     foreach ($grade_grades as $itemid => $unused) {
         $grade_grade =& $grade_grades[$itemid];
         // We need the immediate dependencies of all every grade_item so we can calculate nested dependencies.
         $dependson[$grade_grade->itemid] = $grade_items[$grade_grade->itemid]->depends_on();
         if ($grade_grade->is_excluded()) {
             //nothing to do, aggregation is ok
         } else {
             if ($grade_grade->is_hidden()) {
                 $hiddenfound = true;
                 $altered[$grade_grade->itemid] = null;
                 $alteredaggregationstatus[$grade_grade->itemid] = 'dropped';
                 $alteredaggregationweight[$grade_grade->itemid] = 0;
             } else {
                 if ($grade_grade->is_locked() or $grade_grade->is_overridden()) {
                     // no need to recalculate locked or overridden grades
                 } else {
                     if (!empty($dependson[$grade_grade->itemid])) {
                         $dependencydepth[$grade_grade->itemid] = 1;
                         $todo[] = $grade_grade->itemid;
                     }
                 }
             }
         }
     }
     // Flatten the dependency tree and count number of branches to each leaf.
     self::flatten_dependencies_array($dependson, $dependencydepth);
     if (!$hiddenfound) {
         return array('unknown' => array(), 'altered' => array(), 'alteredgrademax' => array(), 'alteredgrademin' => array(), 'alteredaggregationstatus' => array(), 'alteredaggregationweight' => array());
     }
     // This line ensures that $dependencydepth has the same number of items as $todo.
     $dependencydepth = array_intersect_key($dependencydepth, array_flip($todo));
     // We need to resort the todo list by the dependency depth. This guarantees we process the leaves, then the branches.
     array_multisort($dependencydepth, $todo);
     $max = count($todo);
     $hidden_precursors = null;
     for ($i = 0; $i < $max; $i++) {
         $found = false;
         foreach ($todo as $key => $do) {
             $hidden_precursors = array_intersect($dependson[$do], $unknown);
             if ($hidden_precursors) {
                 // this item depends on hidden grade indirectly
                 $unknown[$do] = $do;
                 unset($todo[$key]);
                 $found = true;
                 continue;
             } else {
                 if (!array_intersect($dependson[$do], $todo)) {
                     $hidden_precursors = array_intersect($dependson[$do], array_keys($altered));
                     if (!$hidden_precursors) {
                         // hiding does not affect this grade
                         unset($todo[$key]);
                         $found = true;
                         continue;
                     } else {
                         // depends on altered grades - we should try to recalculate if possible
                         if ($grade_items[$do]->is_calculated() or !$grade_items[$do]->is_category_item() and !$grade_items[$do]->is_course_item()) {
                             // This is a grade item that is not a category or course and has been affected by grade hiding.
                             // I guess this means it is a calculation that needs to be recalculated.
                             $unknown[$do] = $do;
                             unset($todo[$key]);
                             $found = true;
                             continue;
                         } else {
                             // This is a grade category (or course).
                             $grade_category = $grade_items[$do]->load_item_category();
                             // Build a new list of the grades in this category.
                             $values = array();
                             $immediatedepends = $grade_items[$do]->depends_on();
                             foreach ($immediatedepends as $itemid) {
                                 if (array_key_exists($itemid, $altered)) {
                                     //nulling an altered precursor
                                     $values[$itemid] = $altered[$itemid];
                                     if (is_null($values[$itemid])) {
                                         // This means this was a hidden grade item removed from the result.
                                         unset($values[$itemid]);
                                     }
                                 } elseif (empty($values[$itemid])) {
                                     $values[$itemid] = $grade_grades[$itemid]->finalgrade;
                                 }
                             }
                             foreach ($values as $itemid => $value) {
                                 if ($grade_grades[$itemid]->is_excluded()) {
                                     unset($values[$itemid]);
                                     $alteredaggregationstatus[$itemid] = 'excluded';
                                     $alteredaggregationweight[$itemid] = null;
                                     continue;
                                 }
                                 // The grade min/max may have been altered by hiding.
                                 $grademin = $grade_items[$itemid]->grademin;
                                 if (isset($alteredgrademin[$itemid])) {
                                     $grademin = $alteredgrademin[$itemid];
                                 }
                                 $grademax = $grade_items[$itemid]->grademax;
                                 if (isset($alteredgrademax[$itemid])) {
                                     $grademax = $alteredgrademax[$itemid];
                                 }
                                 $values[$itemid] = grade_grade::standardise_score($value, $grademin, $grademax, 0, 1);
                             }
                             if ($grade_category->aggregateonlygraded) {
                                 foreach ($values as $itemid => $value) {
                                     if (is_null($value)) {
                                         unset($values[$itemid]);
                                         $alteredaggregationstatus[$itemid] = 'novalue';
                                         $alteredaggregationweight[$itemid] = null;
                                     }
                                 }
                             } else {
                                 foreach ($values as $itemid => $value) {
                                     if (is_null($value)) {
                                         $values[$itemid] = 0;
                                     }
                                 }
                             }
                             // limit and sort
                             $allvalues = $values;
                             $grade_category->apply_limit_rules($values, $grade_items);
                             $moredropped = array_diff($allvalues, $values);
                             foreach ($moredropped as $drop => $unused) {
                                 $alteredaggregationstatus[$drop] = 'dropped';
                                 $alteredaggregationweight[$drop] = null;
                             }
                             foreach ($values as $itemid => $val) {
                                 if ($grade_category->is_extracredit_used() && $grade_items[$itemid]->aggregationcoef > 0) {
                                     $alteredaggregationstatus[$itemid] = 'extra';
                                 }
                             }
                             asort($values, SORT_NUMERIC);
                             // let's see we have still enough grades to do any statistics
                             if (count($values) == 0) {
                                 // not enough attempts yet
                                 $altered[$do] = null;
                                 unset($todo[$key]);
                                 $found = true;
                                 continue;
                             }
                             $usedweights = array();
                             $adjustedgrade = $grade_category->aggregate_values_and_adjust_bounds($values, $grade_items, $usedweights);
                             // recalculate the rawgrade back to requested range
                             $finalgrade = grade_grade::standardise_score($adjustedgrade['grade'], 0, 1, $adjustedgrade['grademin'], $adjustedgrade['grademax']);
                             foreach ($usedweights as $itemid => $weight) {
                                 if (!isset($alteredaggregationstatus[$itemid])) {
                                     $alteredaggregationstatus[$itemid] = 'used';
                                 }
                                 $alteredaggregationweight[$itemid] = $weight;
                             }
                             $finalgrade = $grade_items[$do]->bounded_grade($finalgrade);
                             $alteredgrademin[$do] = $adjustedgrade['grademin'];
                             $alteredgrademax[$do] = $adjustedgrade['grademax'];
                             // We need to muck with the "in-memory" grade_items records so
                             // that subsequent calculations will use the adjusted grademin and grademax.
                             $grade_items[$do]->grademin = $adjustedgrade['grademin'];
                             $grade_items[$do]->grademax = $adjustedgrade['grademax'];
                             $altered[$do] = $finalgrade;
                             unset($todo[$key]);
                             $found = true;
                             continue;
                         }
                     }
                 }
             }
         }
         if (!$found) {
             break;
         }
     }
     return array('unknown' => $unknown, 'altered' => $altered, 'alteredgrademax' => $alteredgrademax, 'alteredgrademin' => $alteredgrademin, 'alteredaggregationstatus' => $alteredaggregationstatus, 'alteredaggregationweight' => $alteredaggregationweight);
 }
예제 #13
0
 protected function generate_random_raw_grade($item, $userid)
 {
     $grade = new grade_grade();
     $grade->itemid = $item->id;
     $grade->userid = $userid;
     $grade->grademin = 0;
     $grade->grademax = 1;
     $valuetype = "grade{$item->gradetype}";
     $grade->rawgrade = rand(0, 1000) / 1000;
     $grade->insert();
     return $grade->rawgrade;
 }
예제 #14
0
 /**
  * Return standard meta data for module
  *
  * @param cm_info $mod
  * @param string $timeopenfld
  * @param string $timeclosefld
  * @param string $keyfield
  * @param string $submissiontable
  * @param string $submittedonfld
  * @param string $submitstrkey
  * @param bool $isgradeable
  * @param string $submitselect - sql to further filter submission row select statement - e.g. st.status='finished'
  * @return bool | \theme_snap\activity_meta
  */
 protected static function std_meta(\cm_info $mod, $timeopenfld, $timeclosefld, $keyfield, $submissiontable, $submittedonfld, $submitstrkey, $isgradeable = false, $submitselect = '')
 {
     global $USER;
     $courseid = $mod->course;
     // Create meta data object.
     $meta = new \theme_snap\activity_meta();
     $meta->submitstrkey = $submitstrkey;
     $meta->submittedstr = get_string($submitstrkey, 'theme_snap');
     $meta->notsubmittedstr = get_string('not' . $submitstrkey, 'theme_snap');
     if (get_string_manager()->string_exists($mod->modname . 'draft', 'theme_snap')) {
         $meta->draftstr = get_string($mod->modname . 'draft', 'theme_snap');
     } else {
         $meta->drafstr = get_string('draft', 'theme_snap');
     }
     if (get_string_manager()->string_exists($mod->modname . 'reopened', 'theme_snap')) {
         $meta->reopenedstr = get_string($mod->modname . 'reopened', 'theme_snap');
     } else {
         $meta->reopenedstr = get_string('reopened', 'theme_snap');
     }
     // If module is not visible to the user then don't bother getting meta data.
     if (!$mod->uservisible) {
         return $meta;
     }
     $activitydates = self::instance_activity_dates($courseid, $mod, $timeopenfld, $timeclosefld);
     $meta->timeopen = $activitydates->timeopen;
     $meta->timeclose = $activitydates->timeclose;
     // TODO: use activity specific "teacher" capabilities.
     if (has_capability('mod/assign:grade', \context_course::instance($courseid))) {
         $meta->isteacher = true;
         // Teacher - useful teacher meta data.
         $methodnsubmissions = $mod->modname . '_num_submissions';
         $methodnungraded = $mod->modname . '_num_submissions_ungraded';
         if (method_exists('theme_snap\\activity', $methodnsubmissions)) {
             $meta->numsubmissions = call_user_func('theme_snap\\activity::' . $methodnsubmissions, $courseid, $mod->instance);
         }
         if (method_exists('theme_snap\\activity', $methodnungraded)) {
             $meta->numrequiregrading = call_user_func('theme_snap\\activity::' . $methodnungraded, $courseid, $mod->instance);
         }
     } else {
         // Student - useful student meta data - only display if activity is available.
         if (empty($activitydates->timeopen) || usertime($activitydates->timeopen) <= time()) {
             $submissionrow = self::get_submission_row($courseid, $mod, $submissiontable, $keyfield, $submitselect);
             if (!empty($submissionrow)) {
                 if ($submissionrow->status) {
                     switch ($submissionrow->status) {
                         case 'draft':
                             $meta->draft = true;
                             break;
                         case 'reopened':
                             $meta->reopened = true;
                             break;
                         case 'submitted':
                             $meta->submitted = true;
                             break;
                     }
                 } else {
                     $meta->submitted = true;
                     $meta->timesubmitted = !empty($submissionrow->{$submittedonfld}) ? $submissionrow->{$submittedonfld} : null;
                 }
                 // If submitted on field uses modified field then fall back to timecreated if modified is 0.
                 if (empty($meta->timesubmitted) && ($submittedonfld = 'timemodified')) {
                     if (isset($submissionrow->timemodified)) {
                         $meta->timesubmitted = $submissionrow->timemodified;
                     } else {
                         $meta->timesubmitted = $submissionrow->timecreated;
                     }
                 }
             }
         }
         $graderow = false;
         if ($isgradeable) {
             $graderow = self::grade_row($courseid, $mod);
         }
         if ($graderow) {
             $gradeitem = \grade_item::fetch(array('itemtype' => 'mod', 'itemmodule' => $mod->modname, 'iteminstance' => $mod->instance));
             $grade = new \grade_grade(array('itemid' => $gradeitem->id, 'userid' => $USER->id));
             $coursecontext = \context_course::instance($courseid);
             $canviewhiddengrade = has_capability('moodle/grade:viewhidden', $coursecontext);
             if (!$grade->is_hidden() || $canviewhiddengrade) {
                 $meta->grade = true;
             }
         }
     }
     return $meta;
 }
예제 #15
0
/**
 * Marks user deleted in internal user database and notifies the auth plugin.
 * Also unenrols user from all roles and does other cleanup.
 * @param object $user       Userobject before delete    (without system magic quotes)
 * @return boolean success
 */
function delete_user($user)
{
    global $CFG;
    require_once $CFG->libdir . '/grouplib.php';
    require_once $CFG->libdir . '/gradelib.php';
    require_once $CFG->dirroot . '/message/lib.php';
    begin_sql();
    // delete all grades - backup is kept in grade_grades_history table
    if ($grades = grade_grade::fetch_all(array('userid' => $user->id))) {
        foreach ($grades as $grade) {
            $grade->delete('userdelete');
        }
    }
    //move unread messages from this user to read
    message_move_userfrom_unread2read($user->id);
    // remove from all groups
    delete_records('groups_members', 'userid', $user->id);
    // unenrol from all roles in all contexts
    role_unassign(0, $user->id);
    // this might be slow but it is really needed - modules might do some extra cleanup!
    // now do a final accesslib cleanup - removes all role assingments in user context and context itself
    delete_context(CONTEXT_USER, $user->id);
    require_once $CFG->dirroot . '/tag/lib.php';
    tag_set('user', $user->id, array());
    // workaround for bulk deletes of users with the same email address
    $delname = addslashes("{$user->email}." . time());
    while (record_exists('user', 'username', $delname)) {
        // no need to use mnethostid here
        $delname++;
    }
    // mark internal user record as "deleted"
    $updateuser = new object();
    $updateuser->id = $user->id;
    $updateuser->deleted = 1;
    $updateuser->username = $delname;
    // Remember it just in case
    $updateuser->email = md5($user->username);
    // Store hash of username, useful importing/restoring users
    $updateuser->idnumber = '';
    // Clear this field to free it up
    $updateuser->timemodified = time();
    if (update_record('user', $updateuser)) {
        commit_sql();
        // notify auth plugin - do not block the delete even when plugin fails
        $authplugin = get_auth_plugin($user->auth);
        $authplugin->user_delete($user);
        events_trigger('user_deleted', $user);
        return true;
    } else {
        rollback_sql();
        return false;
    }
}
예제 #16
0
 //$users = $report_evalcomix->load_users();
 //$finalgrades = $report_evalcomix->get_grades();
 $numpages = (int) ($numusers / $studentsperpage);
 if ($numusers % $studentsperpage > 0) {
     $numpages += 1;
 }
 for ($ipage = 0; $ipage < $numpages; ++$ipage) {
     $report_grader = new grade_report_grader($courseid, null, $context, $ipage, $sortitemid);
     $report_grader->load_users();
     $report_grader->load_final_grades();
     foreach ($report_grader->users as $userid => $user) {
         if ($report_grader->canviewhidden) {
             $altered = array();
             $unknown = array();
         } else {
             $hidingaffected = grade_grade::get_hiding_affected($report_grader->grades[$userid], $report_grader->gtree->get_items());
             $altered = $hidingaffected['altered'];
             $unknown = $hidingaffected['unknown'];
             unset($hidingaffected);
         }
         foreach ($report_grader->gtree->items as $itemid => $unused) {
             $item =& $report_grader->gtree->items[$itemid];
             $grade = $report_grader->grades[$userid][$item->id];
             // Get the decimal points preference for this item
             $decimalpoints = $item->get_decimals();
             if (in_array($itemid, $unknown)) {
                 $gradeval = null;
             } else {
                 if (array_key_exists($itemid, $altered)) {
                     $gradeval = $altered[$itemid];
                 } else {
예제 #17
0
/**
 * Grading cron job
 */
function grade_cron()
{
    global $CFG;
    $now = time();
    $sql = "SELECT i.*\n              FROM {$CFG->prefix}grade_items i\n             WHERE i.locked = 0 AND i.locktime > 0 AND i.locktime < {$now} AND EXISTS (\n                SELECT 'x' FROM {$CFG->prefix}grade_items c WHERE c.itemtype='course' AND c.needsupdate=0 AND c.courseid=i.courseid)";
    // go through all courses that have proper final grades and lock them if needed
    if ($rs = get_recordset_sql($sql)) {
        if ($rs->RecordCount() > 0) {
            while ($item = rs_fetch_next_record($rs)) {
                $grade_item = new grade_item($item, false);
                $grade_item->locked = $now;
                $grade_item->update('locktime');
            }
        }
        rs_close($rs);
    }
    $grade_inst = new grade_grade();
    $fields = 'g.' . implode(',g.', $grade_inst->required_fields);
    $sql = "SELECT {$fields}\n              FROM {$CFG->prefix}grade_grades g, {$CFG->prefix}grade_items i\n             WHERE g.locked = 0 AND g.locktime > 0 AND g.locktime < {$now} AND g.itemid=i.id AND EXISTS (\n                SELECT 'x' FROM {$CFG->prefix}grade_items c WHERE c.itemtype='course' AND c.needsupdate=0 AND c.courseid=i.courseid)";
    // go through all courses that have proper final grades and lock them if needed
    if ($rs = get_recordset_sql($sql)) {
        if ($rs->RecordCount() > 0) {
            while ($grade = rs_fetch_next_record($rs)) {
                $grade_grade = new grade_grade($grade, false);
                $grade_grade->locked = $now;
                $grade_grade->update('locktime');
            }
        }
        rs_close($rs);
    }
}
예제 #18
0
 function definition_after_data()
 {
     global $CFG, $COURSE, $DB;
     $context = context_course::instance($COURSE->id);
     $mform =& $this->_form;
     $grade_item = $this->_customdata['grade_item'];
     // fill in user name if user still exists
     $userid = $mform->getElementValue('userid');
     if ($user = $DB->get_record('user', array('id' => $userid))) {
         $username = '******' . $CFG->wwwroot . '/user/view.php?id=' . $userid . '">' . fullname($user) . '</a>';
         $user_el =& $mform->getElement('user');
         $user_el->setValue($username);
     }
     // add activity name + link
     if ($grade_item->itemtype == 'mod') {
         $cm = get_coursemodule_from_instance($grade_item->itemmodule, $grade_item->iteminstance, $grade_item->courseid);
         $itemname = '<a href="' . $CFG->wwwroot . '/mod/' . $grade_item->itemmodule . '/view.php?id=' . $cm->id . '">' . $grade_item->get_name() . '</a>';
     } else {
         $itemname = $grade_item->get_name();
     }
     $itemname_el =& $mform->getElement('itemname');
     $itemname_el->setValue($itemname);
     // access control - disable not allowed elements
     if (!has_capability('moodle/grade:manage', $context)) {
         $mform->hardFreeze('excluded');
     }
     if (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:hide', $context)) {
         $mform->hardFreeze('hidden');
         $mform->hardFreeze('hiddenuntil');
     }
     $old_grade_grade = new grade_grade(array('itemid' => $grade_item->id, 'userid' => $userid));
     if (!$grade_item->is_overridable_item()) {
         $mform->removeElement('overridden');
     }
     if ($grade_item->is_hidden()) {
         $mform->hardFreeze('hidden');
     }
     if ($old_grade_grade->is_locked()) {
         if ($grade_item->is_locked()) {
             $mform->hardFreeze('locked');
             $mform->hardFreeze('locktime');
         }
         $mform->hardFreeze('overridden');
         $mform->hardFreeze('finalgrade');
         $mform->hardFreeze('feedback');
     } else {
         if (empty($old_grade_grade->id)) {
             $old_grade_grade->locked = $grade_item->locked;
             $old_grade_grade->locktime = $grade_item->locktime;
         }
         if (($old_grade_grade->locked or $old_grade_grade->locktime) and (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:unlock', $context))) {
             $mform->hardFreeze('locked');
             $mform->hardFreeze('locktime');
         } else {
             if (!$old_grade_grade->locked and !$old_grade_grade->locktime and (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:lock', $context))) {
                 $mform->hardFreeze('locked');
                 $mform->hardFreeze('locktime');
             }
         }
     }
 }
예제 #19
0
파일: index.php 프로젝트: covex-nn/moodle
     import_cleanup($importcode);
     echo $OUTPUT->notification('user mapping error, could not find user!');
     break;
 }
 if ($separatemode and !groups_is_member($currentgroup, $studentid)) {
     // not allowed to import into this group, abort
     $status = false;
     import_cleanup($importcode);
     echo $OUTPUT->notification('user not member of current group, can not update!');
     break;
 }
 // insert results of this students into buffer
 if ($status and !empty($newgrades)) {
     foreach ($newgrades as $newgrade) {
         // check if grade_grade is locked and if so, abort
         if (!empty($newgrade->itemid) and $grade_grade = new grade_grade(array('itemid' => $newgrade->itemid, 'userid' => $studentid))) {
             if ($grade_grade->is_locked()) {
                 // individual grade locked
                 $status = false;
                 import_cleanup($importcode);
                 echo $OUTPUT->notification(get_string('gradelocked', 'grades'));
                 break 2;
             }
         }
         $newgrade->importcode = $importcode;
         $newgrade->userid = $studentid;
         $newgrade->importer = $USER->id;
         $DB->insert_record('grade_import_values', $newgrade);
     }
 }
 // updating/inserting all comments here
예제 #20
0
파일: grade_item.php 프로젝트: r007/PMoodle
 /**
  * internal function - does the final grade calculation
  */
 function use_formula($userid, $params, $useditems, $oldgrade)
 {
     if (empty($userid)) {
         return true;
     }
     // add missing final grade values
     // not graded (null) is counted as 0 - the spreadsheet way
     foreach ($useditems as $gi) {
         if (!array_key_exists('gi' . $gi, $params)) {
             $params['gi' . $gi] = 0;
         } else {
             $params['gi' . $gi] = (double) $params['gi' . $gi];
         }
     }
     // can not use own final grade during calculation
     unset($params['gi' . $this->id]);
     // insert final grade - will be needed later anyway
     if ($oldgrade) {
         $oldfinalgrade = $oldgrade->finalgrade;
         $grade = new grade_grade($oldgrade, false);
         // fetching from db is not needed
         $grade->grade_item =& $this;
     } else {
         $grade = new grade_grade(array('itemid' => $this->id, 'userid' => $userid), false);
         $grade->grade_item =& $this;
         $grade->insert('system');
         $oldfinalgrade = null;
     }
     // no need to recalculate locked or overridden grades
     if ($grade->is_locked() or $grade->is_overridden()) {
         return true;
     }
     // do the calculation
     $this->formula->set_params($params);
     $result = $this->formula->evaluate();
     if ($result === false) {
         $grade->finalgrade = null;
     } else {
         // normalize
         $result = bounded_number($this->grademin, $result, $this->grademax);
         if ($this->gradetype == GRADE_TYPE_SCALE) {
             $result = round($result + 1.0E-5);
             // round scales upwards
         }
         $grade->finalgrade = $result;
     }
     // update in db if changed
     if (grade_floats_different($grade->finalgrade, $oldfinalgrade)) {
         $grade->update('compute');
     }
     if ($result !== false) {
         //lock grade if needed
     }
     if ($result === false) {
         return false;
     } else {
         return true;
     }
 }
예제 #21
0
 public function fill_table()
 {
     global $CFG, $DB;
     // MDL-11679, only show 'mycourses' instead of all courses
     if ($courses = get_my_courses($this->user->id, 'c.sortorder ASC', 'id, shortname, showgrades')) {
         $numusers = $this->get_numusers(false);
         foreach ($courses as $course) {
             if (!$course->showgrades) {
                 continue;
             }
             $courselink = '<a href="' . $CFG->wwwroot . '/grade/report/user/index.php?id=' . $course->id . '">' . $course->shortname . '</a>';
             $canviewhidden = has_capability('moodle/grade:viewhidden', get_context_instance(CONTEXT_COURSE, $course->id));
             // Get course grade_item
             $course_item = grade_item::fetch_course_item($course->id);
             // Get the stored grade
             $course_grade = new grade_grade(array('itemid' => $course_item->id, 'userid' => $this->user->id));
             $course_grade->grade_item =& $course_item;
             $finalgrade = $course_grade->finalgrade;
             if (!$canviewhidden and !is_null($finalgrade)) {
                 if ($course_grade->is_hidden()) {
                     $finalgrade = null;
                 } else {
                     // This is a really ugly hack, it will be fixed in 2.0
                     $items = grade_item::fetch_all(array('courseid' => $course->id));
                     $grades = array();
                     $sql = "SELECT g.*\n                                  FROM {grade_grades} g\n                                  JOIN {grade_items} gi ON gi.id = g.itemid\n                                 WHERE g.userid = ? AND gi.courseid = ?";
                     if ($gradesrecords = $DB->get_records_sql($sql, array($this->user->id, $course->id))) {
                         foreach ($gradesrecords as $grade) {
                             $grades[$grade->itemid] = new grade_grade($grade, false);
                         }
                         unset($gradesrecords);
                     }
                     foreach ($items as $itemid => $unused) {
                         if (!isset($grades[$itemid])) {
                             $grade_grade = new grade_grade();
                             $grade_grade->userid = $this->user->id;
                             $grade_grade->itemid = $items[$itemid]->id;
                             $grades[$itemid] = $grade_grade;
                         }
                         $grades[$itemid]->grade_item =& $items[$itemid];
                     }
                     $hiding_affected = grade_grade::get_hiding_affected($grades, $items);
                     if (array_key_exists($course_item->id, $hiding_affected['altered'])) {
                         $finalgrade = $hiding_affected['altered'][$course_item->id];
                     } else {
                         if (!empty($hiding_affected['unknown'][$course_item->id])) {
                             $finalgrade = null;
                         }
                     }
                     unset($hiding_affected);
                     unset($grades);
                     unset($items);
                 }
             }
             $data = array($courselink, grade_format_gradevalue($finalgrade, $course_item, true));
             if (!$this->showrank) {
                 //nothing to do
             } else {
                 if (!is_null($finalgrade)) {
                     /// find the number of users with a higher grade
                     /// please note this can not work if hidden grades involved :-( to be fixed in 2.0
                     $params = array($finalgrade, $course_item->id);
                     $sql = "SELECT COUNT(DISTINCT(userid))\n                              FROM {grade_grades}\n                             WHERE finalgrade IS NOT NULL AND finalgrade > ?\n                                   AND itemid = ?";
                     $rank = $DB->count_records_sql($sql, $params) + 1;
                     $data[] = "{$rank}/{$numusers}";
                 } else {
                     // no grade, no rank
                     $data[] = '-';
                 }
             }
             $this->table->add_data($data);
         }
         return true;
     } else {
         notify(get_string('nocourses', 'grades'));
         return false;
     }
 }
예제 #22
0
 /**
  * Optionally blank out course/category totals if they contain any hidden items
  * @param string $courseid the course id
  * @param string $course_item an instance of grade_item
  * @param string $finalgrade the grade for the course_item
  * @return string The new final grade
  */
 protected function blank_hidden_total($courseid, $course_item, $finalgrade)
 {
     global $CFG, $DB;
     static $hiding_affected = null;
     //array of items in this course affected by hiding
     // If we're dealing with multiple users we need to know when we've moved on to a new user.
     static $previous_userid = null;
     // If we're dealing with multiple courses we need to know when we've moved on to a new course.
     static $previous_courseid = null;
     if (!is_array($this->showtotalsifcontainhidden)) {
         debugging('showtotalsifcontainhidden should be an array', DEBUG_DEVELOPER);
         $this->showtotalsifcontainhidden = array($courseid => $this->showtotalsifcontainhidden);
     }
     if ($this->showtotalsifcontainhidden[$courseid] == GRADE_REPORT_SHOW_REAL_TOTAL_IF_CONTAINS_HIDDEN) {
         return $finalgrade;
     }
     // If we've moved on to another course or user, reload the grades.
     if ($previous_userid != $this->user->id || $previous_courseid != $courseid) {
         $hiding_affected = null;
         $previous_userid = $this->user->id;
         $previous_courseid = $courseid;
     }
     if (!$hiding_affected) {
         $items = grade_item::fetch_all(array('courseid' => $courseid));
         $grades = array();
         $sql = "SELECT g.*\n                      FROM {grade_grades} g\n                      JOIN {grade_items} gi ON gi.id = g.itemid\n                     WHERE g.userid = {$this->user->id} AND gi.courseid = {$courseid}";
         if ($gradesrecords = $DB->get_records_sql($sql)) {
             foreach ($gradesrecords as $grade) {
                 $grades[$grade->itemid] = new grade_grade($grade, false);
             }
             unset($gradesrecords);
         }
         foreach ($items as $itemid => $unused) {
             if (!isset($grades[$itemid])) {
                 $grade_grade = new grade_grade();
                 $grade_grade->userid = $this->user->id;
                 $grade_grade->itemid = $items[$itemid]->id;
                 $grades[$itemid] = $grade_grade;
             }
             $grades[$itemid]->grade_item =& $items[$itemid];
         }
         $hiding_affected = grade_grade::get_hiding_affected($grades, $items);
     }
     //if the item definitely depends on a hidden item
     if (array_key_exists($course_item->id, $hiding_affected['altered'])) {
         if (!$this->showtotalsifcontainhidden[$courseid]) {
             //hide the grade
             $finalgrade = null;
         } else {
             //use reprocessed marks that exclude hidden items
             $finalgrade = $hiding_affected['altered'][$course_item->id];
         }
     } else {
         if (!empty($hiding_affected['unknown'][$course_item->id])) {
             //not sure whether or not this item depends on a hidden item
             if (!$this->showtotalsifcontainhidden[$courseid]) {
                 //hide the grade
                 $finalgrade = null;
             } else {
                 //use reprocessed marks that exclude hidden items
                 $finalgrade = $hiding_affected['unknown'][$course_item->id];
             }
         }
     }
     return $finalgrade;
 }
예제 #23
0
 /**
  * Calculates the completion state for an activity and user.
  *
  * Internal function. Not private, so we can unit-test it.
  *
  * @param stdClass|cm_info $cm Activity
  * @param int $userid ID of user
  * @param stdClass $current Previous completion information from database
  * @return mixed
  */
 public function internal_get_state($cm, $userid, $current)
 {
     global $USER, $DB, $CFG;
     // Get user ID
     if (!$userid) {
         $userid = $USER->id;
     }
     // Check viewed
     if ($cm->completionview == COMPLETION_VIEW_REQUIRED && $current->viewed == COMPLETION_NOT_VIEWED) {
         return COMPLETION_INCOMPLETE;
     }
     // Modname hopefully is provided in $cm but just in case it isn't, let's grab it
     if (!isset($cm->modname)) {
         $cm->modname = $DB->get_field('modules', 'name', array('id' => $cm->module));
     }
     $newstate = COMPLETION_COMPLETE;
     // Check grade
     if (!is_null($cm->completiongradeitemnumber)) {
         require_once $CFG->libdir . '/gradelib.php';
         $item = grade_item::fetch(array('courseid' => $cm->course, 'itemtype' => 'mod', 'itemmodule' => $cm->modname, 'iteminstance' => $cm->instance, 'itemnumber' => $cm->completiongradeitemnumber));
         if ($item) {
             // Fetch 'grades' (will be one or none)
             $grades = grade_grade::fetch_users_grades($item, array($userid), false);
             if (empty($grades)) {
                 // No grade for user
                 return COMPLETION_INCOMPLETE;
             }
             if (count($grades) > 1) {
                 $this->internal_systemerror("Unexpected result: multiple grades for\n                        item '{$item->id}', user '{$userid}'");
             }
             $newstate = self::internal_get_grade_state($item, reset($grades));
             if ($newstate == COMPLETION_INCOMPLETE) {
                 return COMPLETION_INCOMPLETE;
             }
         } else {
             $this->internal_systemerror("Cannot find grade item for '{$cm->modname}'\n                    cm '{$cm->id}' matching number '{$cm->completiongradeitemnumber}'");
         }
     }
     if (plugin_supports('mod', $cm->modname, FEATURE_COMPLETION_HAS_RULES)) {
         $function = $cm->modname . '_get_completion_state';
         if (!function_exists($function)) {
             $this->internal_systemerror("Module {$cm->modname} claims to support\n                    FEATURE_COMPLETION_HAS_RULES but does not have required\n                    {$cm->modname}_get_completion_state function");
         }
         if (!$function($this->course, $cm, $userid, COMPLETION_AND)) {
             return COMPLETION_INCOMPLETE;
         }
     }
     return $newstate;
 }
예제 #24
0
/**
 * Returns the aggregated or calculated course grade for the given user(s).
 * @public
 * @param int $userid
 * @param int $courseid optional id of course or array of ids, empty means all uses courses (returns array if not present)
 * @return mixed grade info or grades array including item info, false if error
 */
function grade_get_course_grade($userid, $courseid_or_ids = null)
{
    if (!is_array($courseid_or_ids)) {
        if (empty($courseid_or_ids)) {
            if (!($courses = enrol_get_users_courses($userid))) {
                return false;
            }
            $courseids = array_keys($courses);
            return grade_get_course_grade($userid, $courseids);
        }
        if (!is_numeric($courseid_or_ids)) {
            return false;
        }
        if (!($grades = grade_get_course_grade($userid, array($courseid_or_ids)))) {
            return false;
        } else {
            // only one grade - not array
            $grade = reset($grades);
            return $grade;
        }
    }
    foreach ($courseid_or_ids as $courseid) {
        $grade_item = grade_item::fetch_course_item($courseid);
        $course_items[$grade_item->courseid] = $grade_item;
    }
    $grades = array();
    foreach ($course_items as $grade_item) {
        if ($grade_item->needsupdate) {
            grade_regrade_final_grades($courseid);
        }
        $item = new stdClass();
        $item->scaleid = $grade_item->scaleid;
        $item->name = $grade_item->get_name();
        $item->grademin = $grade_item->grademin;
        $item->grademax = $grade_item->grademax;
        $item->gradepass = $grade_item->gradepass;
        $item->locked = $grade_item->is_locked();
        $item->hidden = $grade_item->is_hidden();
        switch ($grade_item->gradetype) {
            case GRADE_TYPE_NONE:
                continue;
            case GRADE_TYPE_VALUE:
                $item->scaleid = 0;
                break;
            case GRADE_TYPE_TEXT:
                $item->scaleid = 0;
                $item->grademin = 0;
                $item->grademax = 0;
                $item->gradepass = 0;
                break;
        }
        $grade_grade = new grade_grade(array('userid' => $userid, 'itemid' => $grade_item->id));
        $grade_grade->grade_item =& $grade_item;
        $grade = new stdClass();
        $grade->grade = $grade_grade->finalgrade;
        $grade->locked = $grade_grade->is_locked();
        $grade->hidden = $grade_grade->is_hidden();
        $grade->overridden = $grade_grade->overridden;
        $grade->feedback = $grade_grade->feedback;
        $grade->feedbackformat = $grade_grade->feedbackformat;
        $grade->usermodified = $grade_grade->usermodified;
        $grade->dategraded = $grade_grade->get_dategraded();
        $grade->item = $item;
        // create text representation of grade
        if ($grade_item->needsupdate) {
            $grade->grade = false;
            $grade->str_grade = get_string('error');
            $grade->str_long_grade = $grade->str_grade;
        } else {
            if (is_null($grade->grade)) {
                $grade->str_grade = '-';
                $grade->str_long_grade = $grade->str_grade;
            } else {
                $grade->str_grade = grade_format_gradevalue($grade->grade, $grade_item);
                if ($grade_item->gradetype == GRADE_TYPE_SCALE or $grade_item->get_displaytype() != GRADE_DISPLAY_TYPE_REAL) {
                    $grade->str_long_grade = $grade->str_grade;
                } else {
                    $a = new stdClass();
                    $a->grade = $grade->str_grade;
                    $a->max = grade_format_gradevalue($grade_item->grademax, $grade_item);
                    $grade->str_long_grade = get_string('gradelong', 'grades', $a);
                }
            }
        }
        // create html representation of feedback
        if (is_null($grade->feedback)) {
            $grade->str_feedback = '';
        } else {
            $grade->str_feedback = format_text($grade->feedback, $grade->feedbackformat);
        }
        $grades[$grade_item->courseid] = $grade;
    }
    return $grades;
}
예제 #25
0
 protected function process_grade_grade($data)
 {
     $data = (object) $data;
     $olduserid = $data->userid;
     unset($data->id);
     $data->itemid = $this->get_new_parentid('grade_item');
     $data->userid = $this->get_mappingid('user', $data->userid, null);
     if (!empty($data->userid)) {
         $data->usermodified = $this->get_mappingid('user', $data->usermodified, null);
         $data->rawscaleid = $this->get_mappingid('scale', $data->rawscaleid);
         // TODO: Ask, all the rest of locktime/exported... work with time... to be rolled?
         $data->overridden = $this->apply_date_offset($data->overridden);
         $grade = new grade_grade($data, false);
         $grade->insert('restore');
         // no need to save any grade_grade mapping
     } else {
         debugging("Mapped user id not found for user id '{$olduserid}', grade item id '{$data->itemid}'");
     }
 }
예제 #26
0
/**
 * This function creates all the gradebook data from xml
 */
function restore_create_gradebook($restore, $xml_file)
{
    global $CFG;
    $status = true;
    //Check it exists
    if (!file_exists($xml_file)) {
        return false;
    }
    // Get info from xml
    // info will contain the number of record to process
    $info = restore_read_xml_gradebook($restore, $xml_file);
    // If we have info, then process
    if (empty($info)) {
        return $status;
    }
    if (empty($CFG->disablegradehistory) and isset($info->gradebook_histories) and $info->gradebook_histories == "true") {
        $restore_histories = true;
    } else {
        $restore_histories = false;
    }
    // make sure top course category exists
    $course_category = grade_category::fetch_course_category($restore->course_id);
    $course_category->load_grade_item();
    // we need to know if all grade items that were backed up are being restored
    // if that is not the case, we do not restore grade categories nor gradeitems of category type or course type
    // i.e. the aggregated grades of that category
    $restoreall = true;
    // set to false if any grade_item is not selected/restored or already exist
    $importing = !empty($SESSION->restore->importing);
    if ($importing) {
        $restoreall = false;
    } else {
        $prev_grade_items = grade_item::fetch_all(array('courseid' => $restore->course_id));
        $prev_grade_cats = grade_category::fetch_all(array('courseid' => $restore->course_id));
        // if any categories already present, skip restore of categories from backup - course item or category already exist
        if (count($prev_grade_items) > 1 or count($prev_grade_cats) > 1) {
            $restoreall = false;
        }
        unset($prev_grade_items);
        unset($prev_grade_cats);
        if ($restoreall) {
            if ($recs = get_records_select("backup_ids", "table_name = 'grade_items' AND backup_code = {$restore->backup_unique_code}", "", "old_id")) {
                foreach ($recs as $rec) {
                    if ($data = backup_getid($restore->backup_unique_code, 'grade_items', $rec->old_id)) {
                        $info = $data->info;
                        // do not restore if this grade_item is a mod, and
                        $itemtype = backup_todb($info['GRADE_ITEM']['#']['ITEMTYPE']['0']['#']);
                        if ($itemtype == 'mod') {
                            $olditeminstance = backup_todb($info['GRADE_ITEM']['#']['ITEMINSTANCE']['0']['#']);
                            $itemmodule = backup_todb($info['GRADE_ITEM']['#']['ITEMMODULE']['0']['#']);
                            if (empty($restore->mods[$itemmodule]->granular)) {
                                continue;
                            } else {
                                if (!empty($restore->mods[$itemmodule]->instances[$olditeminstance]->restore)) {
                                    continue;
                                }
                            }
                            // at least one activity should not be restored - do not restore categories and manual items at all
                            $restoreall = false;
                            break;
                        }
                    }
                }
            }
        }
    }
    // Start ul
    if (!defined('RESTORE_SILENTLY')) {
        echo '<ul>';
    }
    // array of restored categories - speedup ;-)
    $cached_categories = array();
    $outcomes = array();
    /// Process letters
    $context = get_context_instance(CONTEXT_COURSE, $restore->course_id);
    // respect current grade letters if defined
    if ($status and $restoreall and !record_exists('grade_letters', 'contextid', $context->id)) {
        if (!defined('RESTORE_SILENTLY')) {
            echo '<li>' . get_string('gradeletters', 'grades') . '</li>';
        }
        // Fetch recordset_size records in each iteration
        $recs = get_records_select("backup_ids", "table_name = 'grade_letters' AND backup_code = {$restore->backup_unique_code}", "", "old_id");
        if ($recs) {
            foreach ($recs as $rec) {
                // Get the full record from backup_ids
                $data = backup_getid($restore->backup_unique_code, 'grade_letters', $rec->old_id);
                if ($data) {
                    $info = $data->info;
                    $dbrec = new object();
                    $dbrec->contextid = $context->id;
                    $dbrec->lowerboundary = backup_todb($info['GRADE_LETTER']['#']['LOWERBOUNDARY']['0']['#']);
                    $dbrec->letter = backup_todb($info['GRADE_LETTER']['#']['LETTER']['0']['#']);
                    insert_record('grade_letters', $dbrec);
                }
            }
        }
    }
    /// Preprocess outcomes - do not store them yet!
    if ($status and !$importing and $restoreall) {
        if (!defined('RESTORE_SILENTLY')) {
            echo '<li>' . get_string('gradeoutcomes', 'grades') . '</li>';
        }
        $recs = get_records_select("backup_ids", "table_name = 'grade_outcomes' AND backup_code = '{$restore->backup_unique_code}'", "", "old_id");
        if ($recs) {
            foreach ($recs as $rec) {
                //Get the full record from backup_ids
                $data = backup_getid($restore->backup_unique_code, 'grade_outcomes', $rec->old_id);
                if ($data) {
                    $info = $data->info;
                    //first find out if outcome already exists
                    $shortname = backup_todb($info['GRADE_OUTCOME']['#']['SHORTNAME']['0']['#']);
                    if ($candidates = get_records_sql("SELECT *\n                                                             FROM {$CFG->prefix}grade_outcomes\n                                                            WHERE (courseid IS NULL OR courseid = {$restore->course_id})\n                                                                  AND shortname = '{$shortname}'\n                                                         ORDER BY courseid ASC, id ASC")) {
                        $grade_outcome = reset($candidates);
                        $outcomes[$rec->old_id] = $grade_outcome;
                        continue;
                    }
                    $dbrec = new object();
                    if (has_capability('moodle/grade:manageoutcomes', get_context_instance(CONTEXT_SYSTEM))) {
                        $oldoutcome = backup_todb($info['GRADE_OUTCOME']['#']['COURSEID']['0']['#']);
                        if (empty($oldoutcome)) {
                            //site wide
                            $dbrec->courseid = null;
                        } else {
                            //course only
                            $dbrec->courseid = $restore->course_id;
                        }
                    } else {
                        // no permission to add site outcomes
                        $dbrec->courseid = $restore->course_id;
                    }
                    //Get the fields
                    $dbrec->shortname = backup_todb($info['GRADE_OUTCOME']['#']['SHORTNAME']['0']['#'], false);
                    $dbrec->fullname = backup_todb($info['GRADE_OUTCOME']['#']['FULLNAME']['0']['#'], false);
                    $dbrec->scaleid = backup_todb($info['GRADE_OUTCOME']['#']['SCALEID']['0']['#'], false);
                    $dbrec->description = backup_todb($info['GRADE_OUTCOME']['#']['DESCRIPTION']['0']['#'], false);
                    $dbrec->timecreated = backup_todb($info['GRADE_OUTCOME']['#']['TIMECREATED']['0']['#'], false);
                    $dbrec->timemodified = backup_todb($info['GRADE_OUTCOME']['#']['TIMEMODIFIED']['0']['#'], false);
                    $dbrec->usermodified = backup_todb($info['GRADE_OUTCOME']['#']['USERMODIFIED']['0']['#'], false);
                    //Need to recode the scaleid
                    if ($scale = backup_getid($restore->backup_unique_code, 'scale', $dbrec->scaleid)) {
                        $dbrec->scaleid = $scale->new_id;
                    }
                    //Need to recode the usermodified
                    if ($modifier = backup_getid($restore->backup_unique_code, 'user', $dbrec->usermodified)) {
                        $dbrec->usermodified = $modifier->new_id;
                    }
                    $grade_outcome = new grade_outcome($dbrec, false);
                    $outcomes[$rec->old_id] = $grade_outcome;
                }
            }
        }
    }
    /// Process grade items and grades
    if ($status) {
        if (!defined('RESTORE_SILENTLY')) {
            echo '<li>' . get_string('gradeitems', 'grades') . '</li>';
        }
        $counter = 0;
        //Fetch recordset_size records in each iteration
        $recs = get_records_select("backup_ids", "table_name = 'grade_items' AND backup_code = '{$restore->backup_unique_code}'", "id", "old_id");
        if ($recs) {
            foreach ($recs as $rec) {
                //Get the full record from backup_ids
                $data = backup_getid($restore->backup_unique_code, 'grade_items', $rec->old_id);
                if ($data) {
                    $info = $data->info;
                    // first find out if category or normal item
                    $itemtype = backup_todb($info['GRADE_ITEM']['#']['ITEMTYPE']['0']['#'], false);
                    if ($itemtype == 'course' or $itemtype == 'category') {
                        if (!$restoreall or $importing) {
                            continue;
                        }
                        $oldcat = backup_todb($info['GRADE_ITEM']['#']['ITEMINSTANCE']['0']['#'], false);
                        if (!($cdata = backup_getid($restore->backup_unique_code, 'grade_categories', $oldcat))) {
                            continue;
                        }
                        $cinfo = $cdata->info;
                        unset($cdata);
                        if ($itemtype == 'course') {
                            $course_category->fullname = backup_todb($cinfo['GRADE_CATEGORY']['#']['FULLNAME']['0']['#'], false);
                            $course_category->aggregation = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATION']['0']['#'], false);
                            $course_category->keephigh = backup_todb($cinfo['GRADE_CATEGORY']['#']['KEEPHIGH']['0']['#'], false);
                            $course_category->droplow = backup_todb($cinfo['GRADE_CATEGORY']['#']['DROPLOW']['0']['#'], false);
                            $course_category->aggregateonlygraded = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATEONLYGRADED']['0']['#'], false);
                            $course_category->aggregateoutcomes = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATEOUTCOMES']['0']['#'], false);
                            $course_category->aggregatesubcats = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATESUBCATS']['0']['#'], false);
                            $course_category->timecreated = backup_todb($cinfo['GRADE_CATEGORY']['#']['TIMECREATED']['0']['#'], false);
                            $course_category->update('restore');
                            $status = backup_putid($restore->backup_unique_code, 'grade_categories', $oldcat, $course_category->id) && $status;
                            $cached_categories[$oldcat] = $course_category;
                            $grade_item = $course_category->get_grade_item();
                        } else {
                            $oldparent = backup_todb($cinfo['GRADE_CATEGORY']['#']['PARENT']['0']['#'], false);
                            if (empty($cached_categories[$oldparent])) {
                                debugging('parent not found ' . $oldparent);
                                continue;
                                // parent not found, sorry
                            }
                            $grade_category = new grade_category();
                            $grade_category->courseid = $restore->course_id;
                            $grade_category->parent = $cached_categories[$oldparent]->id;
                            $grade_category->fullname = backup_todb($cinfo['GRADE_CATEGORY']['#']['FULLNAME']['0']['#'], false);
                            $grade_category->aggregation = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATION']['0']['#'], false);
                            $grade_category->keephigh = backup_todb($cinfo['GRADE_CATEGORY']['#']['KEEPHIGH']['0']['#'], false);
                            $grade_category->droplow = backup_todb($cinfo['GRADE_CATEGORY']['#']['DROPLOW']['0']['#'], false);
                            $grade_category->aggregateonlygraded = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATEONLYGRADED']['0']['#'], false);
                            $grade_category->aggregateoutcomes = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATEOUTCOMES']['0']['#'], false);
                            $grade_category->aggregatesubcats = backup_todb($cinfo['GRADE_CATEGORY']['#']['AGGREGATESUBCATS']['0']['#'], false);
                            $grade_category->timecreated = backup_todb($cinfo['GRADE_CATEGORY']['#']['TIMECREATED']['0']['#'], false);
                            $grade_category->insert('restore');
                            $status = backup_putid($restore->backup_unique_code, 'grade_categories', $oldcat, $grade_category->id) && $status;
                            $cached_categories[$oldcat] = $grade_category;
                            $grade_item = $grade_category->get_grade_item();
                            // creates grade_item too
                        }
                        unset($cinfo);
                        $idnumber = backup_todb($info['GRADE_ITEM']['#']['IDNUMBER']['0']['#'], false);
                        if (grade_verify_idnumber($idnumber, $restore->course_id)) {
                            $grade_item->idnumber = $idnumber;
                        }
                        $grade_item->itemname = backup_todb($info['GRADE_ITEM']['#']['ITEMNAME']['0']['#'], false);
                        $grade_item->iteminfo = backup_todb($info['GRADE_ITEM']['#']['ITEMINFO']['0']['#'], false);
                        $grade_item->gradetype = backup_todb($info['GRADE_ITEM']['#']['GRADETYPE']['0']['#'], false);
                        $grade_item->calculation = backup_todb($info['GRADE_ITEM']['#']['CALCULATION']['0']['#'], false);
                        $grade_item->grademax = backup_todb($info['GRADE_ITEM']['#']['GRADEMAX']['0']['#'], false);
                        $grade_item->grademin = backup_todb($info['GRADE_ITEM']['#']['GRADEMIN']['0']['#'], false);
                        $grade_item->gradepass = backup_todb($info['GRADE_ITEM']['#']['GRADEPASS']['0']['#'], false);
                        $grade_item->multfactor = backup_todb($info['GRADE_ITEM']['#']['MULTFACTOR']['0']['#'], false);
                        $grade_item->plusfactor = backup_todb($info['GRADE_ITEM']['#']['PLUSFACTOR']['0']['#'], false);
                        $grade_item->aggregationcoef = backup_todb($info['GRADE_ITEM']['#']['AGGREGATIONCOEF']['0']['#'], false);
                        $grade_item->display = backup_todb($info['GRADE_ITEM']['#']['DISPLAY']['0']['#'], false);
                        $grade_item->decimals = backup_todb($info['GRADE_ITEM']['#']['DECIMALS']['0']['#'], false);
                        $grade_item->hidden = backup_todb($info['GRADE_ITEM']['#']['HIDDEN']['0']['#'], false);
                        $grade_item->locked = backup_todb($info['GRADE_ITEM']['#']['LOCKED']['0']['#'], false);
                        $grade_item->locktime = backup_todb($info['GRADE_ITEM']['#']['LOCKTIME']['0']['#'], false);
                        $grade_item->timecreated = backup_todb($info['GRADE_ITEM']['#']['TIMECREATED']['0']['#'], false);
                        if (backup_todb($info['GRADE_ITEM']['#']['SCALEID']['0']['#'], false)) {
                            $scale = backup_getid($restore->backup_unique_code, "scale", backup_todb($info['GRADE_ITEM']['#']['SCALEID']['0']['#'], false));
                            $grade_item->scaleid = $scale->new_id;
                        }
                        if (backup_todb($info['GRADE_ITEM']['#']['OUTCOMEID']['0']['#'], false)) {
                            $outcome = backup_getid($restore->backup_unique_code, "grade_outcomes", backup_todb($info['GRADE_ITEM']['#']['OUTCOMEID']['0']['#'], false));
                            $grade_item->outcomeid = $outcome->new_id;
                        }
                        $grade_item->update('restore');
                        $status = backup_putid($restore->backup_unique_code, "grade_items", $rec->old_id, $grade_item->id) && $status;
                    } else {
                        if ($itemtype != 'mod' and (!$restoreall or $importing)) {
                            // not extra gradebook stuff if restoring individual activities or something already there
                            continue;
                        }
                        $dbrec = new object();
                        $dbrec->courseid = $restore->course_id;
                        $dbrec->itemtype = backup_todb($info['GRADE_ITEM']['#']['ITEMTYPE']['0']['#'], false);
                        $dbrec->itemmodule = backup_todb($info['GRADE_ITEM']['#']['ITEMMODULE']['0']['#'], false);
                        if ($itemtype == 'mod') {
                            // iteminstance should point to new mod
                            $olditeminstance = backup_todb($info['GRADE_ITEM']['#']['ITEMINSTANCE']['0']['#'], false);
                            $mod = backup_getid($restore->backup_unique_code, $dbrec->itemmodule, $olditeminstance);
                            $dbrec->iteminstance = $mod->new_id;
                            if (!($cm = get_coursemodule_from_instance($dbrec->itemmodule, $mod->new_id))) {
                                // item not restored - no item
                                continue;
                            }
                            // keep in sync with activity idnumber
                            $dbrec->idnumber = $cm->idnumber;
                        } else {
                            $idnumber = backup_todb($info['GRADE_ITEM']['#']['IDNUMBER']['0']['#'], false);
                            if (grade_verify_idnumber($idnumber, $restore->course_id)) {
                                //make sure the new idnumber is unique
                                $dbrec->idnumber = $idnumber;
                            }
                        }
                        $dbrec->itemname = backup_todb($info['GRADE_ITEM']['#']['ITEMNAME']['0']['#'], false);
                        $dbrec->itemtype = backup_todb($info['GRADE_ITEM']['#']['ITEMTYPE']['0']['#'], false);
                        $dbrec->itemmodule = backup_todb($info['GRADE_ITEM']['#']['ITEMMODULE']['0']['#'], false);
                        $dbrec->itemnumber = backup_todb($info['GRADE_ITEM']['#']['ITEMNUMBER']['0']['#'], false);
                        $dbrec->iteminfo = backup_todb($info['GRADE_ITEM']['#']['ITEMINFO']['0']['#'], false);
                        $dbrec->gradetype = backup_todb($info['GRADE_ITEM']['#']['GRADETYPE']['0']['#'], false);
                        $dbrec->calculation = backup_todb($info['GRADE_ITEM']['#']['CALCULATION']['0']['#'], false);
                        $dbrec->grademax = backup_todb($info['GRADE_ITEM']['#']['GRADEMAX']['0']['#'], false);
                        $dbrec->grademin = backup_todb($info['GRADE_ITEM']['#']['GRADEMIN']['0']['#'], false);
                        $dbrec->gradepass = backup_todb($info['GRADE_ITEM']['#']['GRADEPASS']['0']['#'], false);
                        $dbrec->multfactor = backup_todb($info['GRADE_ITEM']['#']['MULTFACTOR']['0']['#'], false);
                        $dbrec->plusfactor = backup_todb($info['GRADE_ITEM']['#']['PLUSFACTOR']['0']['#'], false);
                        $dbrec->aggregationcoef = backup_todb($info['GRADE_ITEM']['#']['AGGREGATIONCOEF']['0']['#'], false);
                        $dbrec->display = backup_todb($info['GRADE_ITEM']['#']['DISPLAY']['0']['#'], false);
                        $dbrec->decimals = backup_todb($info['GRADE_ITEM']['#']['DECIMALS']['0']['#'], false);
                        $dbrec->hidden = backup_todb($info['GRADE_ITEM']['#']['HIDDEN']['0']['#'], false);
                        $dbrec->locked = backup_todb($info['GRADE_ITEM']['#']['LOCKED']['0']['#'], false);
                        $dbrec->locktime = backup_todb($info['GRADE_ITEM']['#']['LOCKTIME']['0']['#'], false);
                        $dbrec->timecreated = backup_todb($info['GRADE_ITEM']['#']['TIMECREATED']['0']['#'], false);
                        if (backup_todb($info['GRADE_ITEM']['#']['SCALEID']['0']['#'], false)) {
                            $scale = backup_getid($restore->backup_unique_code, "scale", backup_todb($info['GRADE_ITEM']['#']['SCALEID']['0']['#'], false));
                            $dbrec->scaleid = $scale->new_id;
                        }
                        if (backup_todb($info['GRADE_ITEM']['#']['OUTCOMEID']['0']['#'])) {
                            $oldoutcome = backup_todb($info['GRADE_ITEM']['#']['OUTCOMEID']['0']['#']);
                            if (empty($outcomes[$oldoutcome])) {
                                continue;
                                // error!
                            }
                            if (empty($outcomes[$oldoutcome]->id)) {
                                $outcomes[$oldoutcome]->insert('restore');
                                $outcomes[$oldoutcome]->use_in($restore->course_id);
                                backup_putid($restore->backup_unique_code, "grade_outcomes", $oldoutcome, $outcomes[$oldoutcome]->id);
                            }
                            $dbrec->outcomeid = $outcomes[$oldoutcome]->id;
                        }
                        $grade_item = new grade_item($dbrec, false);
                        $grade_item->insert('restore');
                        if ($restoreall) {
                            // set original parent if restored
                            $oldcat = $info['GRADE_ITEM']['#']['CATEGORYID']['0']['#'];
                            if (!empty($cached_categories[$oldcat])) {
                                $grade_item->set_parent($cached_categories[$oldcat]->id);
                            }
                        }
                        $status = backup_putid($restore->backup_unique_code, "grade_items", $rec->old_id, $grade_item->id) && $status;
                    }
                    // no need to restore grades if user data is not selected or importing activities
                    if ($importing or $grade_item->itemtype == 'mod' and !restore_userdata_selected($restore, $grade_item->itemmodule, $olditeminstance)) {
                        // module instance not selected when restored using granular
                        // skip this item
                        continue;
                    }
                    /// now, restore grade_grades
                    if (!empty($info['GRADE_ITEM']['#']['GRADE_GRADES']['0']['#']['GRADE'])) {
                        //Iterate over items
                        foreach ($info['GRADE_ITEM']['#']['GRADE_GRADES']['0']['#']['GRADE'] as $g_info) {
                            $grade = new grade_grade();
                            $grade->itemid = $grade_item->id;
                            $olduser = backup_todb($g_info['#']['USERID']['0']['#'], false);
                            $user = backup_getid($restore->backup_unique_code, "user", $olduser);
                            $grade->userid = $user->new_id;
                            $grade->rawgrade = backup_todb($g_info['#']['RAWGRADE']['0']['#'], false);
                            $grade->rawgrademax = backup_todb($g_info['#']['RAWGRADEMAX']['0']['#'], false);
                            $grade->rawgrademin = backup_todb($g_info['#']['RAWGRADEMIN']['0']['#'], false);
                            // need to find scaleid
                            if (backup_todb($g_info['#']['RAWSCALEID']['0']['#'])) {
                                $scale = backup_getid($restore->backup_unique_code, "scale", backup_todb($g_info['#']['RAWSCALEID']['0']['#'], false));
                                $grade->rawscaleid = $scale->new_id;
                            }
                            if (backup_todb($g_info['#']['USERMODIFIED']['0']['#'])) {
                                if ($modifier = backup_getid($restore->backup_unique_code, "user", backup_todb($g_info['#']['USERMODIFIED']['0']['#'], false))) {
                                    $grade->usermodified = $modifier->new_id;
                                }
                            }
                            $grade->finalgrade = backup_todb($g_info['#']['FINALGRADE']['0']['#'], false);
                            $grade->hidden = backup_todb($g_info['#']['HIDDEN']['0']['#'], false);
                            $grade->locked = backup_todb($g_info['#']['LOCKED']['0']['#'], false);
                            $grade->locktime = backup_todb($g_info['#']['LOCKTIME']['0']['#'], false);
                            $grade->exported = backup_todb($g_info['#']['EXPORTED']['0']['#'], false);
                            $grade->overridden = backup_todb($g_info['#']['OVERRIDDEN']['0']['#'], false);
                            $grade->excluded = backup_todb($g_info['#']['EXCLUDED']['0']['#'], false);
                            $grade->feedback = backup_todb($g_info['#']['FEEDBACK']['0']['#'], false);
                            $grade->feedbackformat = backup_todb($g_info['#']['FEEDBACKFORMAT']['0']['#'], false);
                            $grade->information = backup_todb($g_info['#']['INFORMATION']['0']['#'], false);
                            $grade->informationformat = backup_todb($g_info['#']['INFORMATIONFORMAT']['0']['#'], false);
                            $grade->timecreated = backup_todb($g_info['#']['TIMECREATED']['0']['#'], false);
                            $grade->timemodified = backup_todb($g_info['#']['TIMEMODIFIED']['0']['#'], false);
                            $grade->insert('restore');
                            backup_putid($restore->backup_unique_code, "grade_grades", backup_todb($g_info['#']['ID']['0']['#']), $grade->id);
                            $counter++;
                            if ($counter % 20 == 0) {
                                if (!defined('RESTORE_SILENTLY')) {
                                    echo ".";
                                    if ($counter % 400 == 0) {
                                        echo "<br />";
                                    }
                                }
                                backup_flush(300);
                            }
                        }
                    }
                }
            }
        }
    }
    /// add outcomes that are not used when doing full restore
    if ($status and $restoreall) {
        foreach ($outcomes as $oldoutcome => $grade_outcome) {
            if (empty($grade_outcome->id)) {
                $grade_outcome->insert('restore');
                $grade_outcome->use_in($restore->course_id);
                backup_putid($restore->backup_unique_code, "grade_outcomes", $oldoutcome, $grade_outcome->id);
            }
        }
    }
    if ($status and !$importing and $restore_histories) {
        /// following code is very inefficient
        $gchcount = count_records('backup_ids', 'backup_code', $restore->backup_unique_code, 'table_name', 'grade_categories_history');
        $gghcount = count_records('backup_ids', 'backup_code', $restore->backup_unique_code, 'table_name', 'grade_grades_history');
        $gihcount = count_records('backup_ids', 'backup_code', $restore->backup_unique_code, 'table_name', 'grade_items_history');
        $gohcount = count_records('backup_ids', 'backup_code', $restore->backup_unique_code, 'table_name', 'grade_outcomes_history');
        // Number of records to get in every chunk
        $recordset_size = 2;
        // process histories
        if ($gchcount && $status) {
            if (!defined('RESTORE_SILENTLY')) {
                echo '<li>' . get_string('gradecategoryhistory', 'grades') . '</li>';
            }
            $counter = 0;
            while ($counter < $gchcount) {
                //Fetch recordset_size records in each iteration
                $recs = get_records_select("backup_ids", "table_name = 'grade_categories_history' AND backup_code = '{$restore->backup_unique_code}'", "old_id", "old_id", $counter, $recordset_size);
                if ($recs) {
                    foreach ($recs as $rec) {
                        //Get the full record from backup_ids
                        $data = backup_getid($restore->backup_unique_code, 'grade_categories_history', $rec->old_id);
                        if ($data) {
                            //Now get completed xmlized object
                            $info = $data->info;
                            //traverse_xmlize($info);                            //Debug
                            //print_object ($GLOBALS['traverse_array']);         //Debug
                            //$GLOBALS['traverse_array']="";                     //Debug
                            $oldobj = backup_getid($restore->backup_unique_code, "grade_categories", backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['OLDID']['0']['#']));
                            if (empty($oldobj->new_id)) {
                                // if the old object is not being restored, can't restoring its history
                                $counter++;
                                continue;
                            }
                            $dbrec->oldid = $oldobj->new_id;
                            $dbrec->action = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['ACTION']['0']['#']);
                            $dbrec->source = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['SOURCE']['0']['#']);
                            $dbrec->timemodified = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['TIMEMODIFIED']['0']['#']);
                            // loggeduser might not be restored, e.g. admin
                            if ($oldobj = backup_getid($restore->backup_unique_code, "user", backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['LOGGEDUSER']['0']['#']))) {
                                $dbrec->loggeduser = $oldobj->new_id;
                            }
                            // this item might not have a parent at all, do not skip it if no parent is specified
                            if (backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['PARENT']['0']['#'])) {
                                $oldobj = backup_getid($restore->backup_unique_code, "grade_categories", backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['PARENT']['0']['#']));
                                if (empty($oldobj->new_id)) {
                                    // if the parent category not restored
                                    $counter++;
                                    continue;
                                }
                            }
                            $dbrec->parent = $oldobj->new_id;
                            $dbrec->depth = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['DEPTH']['0']['#']);
                            // path needs to be rebuilt
                            if ($path = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['PATH']['0']['#'])) {
                                // to preserve the path and make it work, we need to replace the categories one by one
                                // we first get the list of categories in current path
                                if ($paths = explode("/", $path)) {
                                    $newpath = '';
                                    foreach ($paths as $catid) {
                                        if ($catid) {
                                            // find the new corresponding path
                                            $oldpath = backup_getid($restore->backup_unique_code, "grade_categories", $catid);
                                            $newpath .= "/{$oldpath->new_id}";
                                        }
                                    }
                                    $dbrec->path = $newpath;
                                }
                            }
                            $dbrec->fullname = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['FULLNAME']['0']['#']);
                            $dbrec->aggregation = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['AGGRETGATION']['0']['#']);
                            $dbrec->keephigh = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['KEEPHIGH']['0']['#']);
                            $dbrec->droplow = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['DROPLOW']['0']['#']);
                            $dbrec->aggregateonlygraded = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['AGGREGATEONLYGRADED']['0']['#']);
                            $dbrec->aggregateoutcomes = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['AGGREGATEOUTCOMES']['0']['#']);
                            $dbrec->aggregatesubcats = backup_todb($info['GRADE_CATEGORIES_HISTORY']['#']['AGGREGATESUBCATS']['0']['#']);
                            $dbrec->courseid = $restore->course_id;
                            insert_record('grade_categories_history', $dbrec);
                            unset($dbrec);
                        }
                        //Increment counters
                        $counter++;
                        //Do some output
                        if ($counter % 1 == 0) {
                            if (!defined('RESTORE_SILENTLY')) {
                                echo ".";
                                if ($counter % 20 == 0) {
                                    echo "<br />";
                                }
                            }
                            backup_flush(300);
                        }
                    }
                }
            }
        }
        // process histories
        if ($gghcount && $status) {
            if (!defined('RESTORE_SILENTLY')) {
                echo '<li>' . get_string('gradegradeshistory', 'grades') . '</li>';
            }
            $counter = 0;
            while ($counter < $gghcount) {
                //Fetch recordset_size records in each iteration
                $recs = get_records_select("backup_ids", "table_name = 'grade_grades_history' AND backup_code = '{$restore->backup_unique_code}'", "old_id", "old_id", $counter, $recordset_size);
                if ($recs) {
                    foreach ($recs as $rec) {
                        //Get the full record from backup_ids
                        $data = backup_getid($restore->backup_unique_code, 'grade_grades_history', $rec->old_id);
                        if ($data) {
                            //Now get completed xmlized object
                            $info = $data->info;
                            //traverse_xmlize($info);                            //Debug
                            //print_object ($GLOBALS['traverse_array']);         //Debug
                            //$GLOBALS['traverse_array']="";                     //Debug
                            $oldobj = backup_getid($restore->backup_unique_code, "grade_grades", backup_todb($info['GRADE_GRADES_HISTORY']['#']['OLDID']['0']['#']));
                            if (empty($oldobj->new_id)) {
                                // if the old object is not being restored, can't restoring its history
                                $counter++;
                                continue;
                            }
                            $dbrec->oldid = $oldobj->new_id;
                            $dbrec->action = backup_todb($info['GRADE_GRADES_HISTORY']['#']['ACTION']['0']['#']);
                            $dbrec->source = backup_todb($info['GRADE_GRADES_HISTORY']['#']['SOURCE']['0']['#']);
                            $dbrec->timemodified = backup_todb($info['GRADE_GRADES_HISTORY']['#']['TIMEMODIFIED']['0']['#']);
                            if ($oldobj = backup_getid($restore->backup_unique_code, "user", backup_todb($info['GRADE_GRADES_HISTORY']['#']['LOGGEDUSER']['0']['#']))) {
                                $dbrec->loggeduser = $oldobj->new_id;
                            }
                            $oldobj = backup_getid($restore->backup_unique_code, "grade_items", backup_todb($info['GRADE_GRADES_HISTORY']['#']['ITEMID']['0']['#']));
                            $dbrec->itemid = $oldobj->new_id;
                            if (empty($dbrec->itemid)) {
                                $counter++;
                                continue;
                                // grade item not being restored
                            }
                            $oldobj = backup_getid($restore->backup_unique_code, "user", backup_todb($info['GRADE_GRADES_HISTORY']['#']['USERID']['0']['#']));
                            $dbrec->userid = $oldobj->new_id;
                            $dbrec->rawgrade = backup_todb($info['GRADE_GRADES_HISTORY']['#']['RAWGRADE']['0']['#']);
                            $dbrec->rawgrademax = backup_todb($info['GRADE_GRADES_HISTORY']['#']['RAWGRADEMAX']['0']['#']);
                            $dbrec->rawgrademin = backup_todb($info['GRADE_GRADES_HISTORY']['#']['RAWGRADEMIN']['0']['#']);
                            if ($oldobj = backup_getid($restore->backup_unique_code, "user", backup_todb($info['GRADE_GRADES_HISTORY']['#']['USERMODIFIED']['0']['#']))) {
                                $dbrec->usermodified = $oldobj->new_id;
                            }
                            if (backup_todb($info['GRADE_GRADES_HISTORY']['#']['RAWSCALEID']['0']['#'])) {
                                $scale = backup_getid($restore->backup_unique_code, "scale", backup_todb($info['GRADE_GRADES_HISTORY']['#']['RAWSCALEID']['0']['#']));
                                $dbrec->rawscaleid = $scale->new_id;
                            }
                            $dbrec->finalgrade = backup_todb($info['GRADE_GRADES_HISTORY']['#']['FINALGRADE']['0']['#']);
                            $dbrec->hidden = backup_todb($info['GRADE_GRADES_HISTORY']['#']['HIDDEN']['0']['#']);
                            $dbrec->locked = backup_todb($info['GRADE_GRADES_HISTORY']['#']['LOCKED']['0']['#']);
                            $dbrec->locktime = backup_todb($info['GRADE_GRADES_HISTORY']['#']['LOCKTIME']['0']['#']);
                            $dbrec->exported = backup_todb($info['GRADE_GRADES_HISTORY']['#']['EXPORTED']['0']['#']);
                            $dbrec->overridden = backup_todb($info['GRADE_GRADES_HISTORY']['#']['OVERRIDDEN']['0']['#']);
                            $dbrec->excluded = backup_todb($info['GRADE_GRADES_HISTORY']['#']['EXCLUDED']['0']['#']);
                            $dbrec->feedback = backup_todb($info['GRADE_TEXT_HISTORY']['#']['FEEDBACK']['0']['#']);
                            $dbrec->feedbackformat = backup_todb($info['GRADE_TEXT_HISTORY']['#']['FEEDBACKFORMAT']['0']['#']);
                            $dbrec->information = backup_todb($info['GRADE_TEXT_HISTORY']['#']['INFORMATION']['0']['#']);
                            $dbrec->informationformat = backup_todb($info['GRADE_TEXT_HISTORY']['#']['INFORMATIONFORMAT']['0']['#']);
                            insert_record('grade_grades_history', $dbrec);
                            unset($dbrec);
                        }
                        //Increment counters
                        $counter++;
                        //Do some output
                        if ($counter % 1 == 0) {
                            if (!defined('RESTORE_SILENTLY')) {
                                echo ".";
                                if ($counter % 20 == 0) {
                                    echo "<br />";
                                }
                            }
                            backup_flush(300);
                        }
                    }
                }
            }
        }
        // process histories
        if ($gihcount && $status) {
            if (!defined('RESTORE_SILENTLY')) {
                echo '<li>' . get_string('gradeitemshistory', 'grades') . '</li>';
            }
            $counter = 0;
            while ($counter < $gihcount) {
                //Fetch recordset_size records in each iteration
                $recs = get_records_select("backup_ids", "table_name = 'grade_items_history' AND backup_code = '{$restore->backup_unique_code}'", "old_id", "old_id", $counter, $recordset_size);
                if ($recs) {
                    foreach ($recs as $rec) {
                        //Get the full record from backup_ids
                        $data = backup_getid($restore->backup_unique_code, 'grade_items_history', $rec->old_id);
                        if ($data) {
                            //Now get completed xmlized object
                            $info = $data->info;
                            //traverse_xmlize($info);                            //Debug
                            //print_object ($GLOBALS['traverse_array']);         //Debug
                            //$GLOBALS['traverse_array']="";                     //Debug
                            $oldobj = backup_getid($restore->backup_unique_code, "grade_items", backup_todb($info['GRADE_ITEM_HISTORY']['#']['OLDID']['0']['#']));
                            if (empty($oldobj->new_id)) {
                                // if the old object is not being restored, can't restoring its history
                                $counter++;
                                continue;
                            }
                            $dbrec->oldid = $oldobj->new_id;
                            $dbrec->action = backup_todb($info['GRADE_ITEM_HISTORY']['#']['ACTION']['0']['#']);
                            $dbrec->source = backup_todb($info['GRADE_ITEM_HISTORY']['#']['SOURCE']['0']['#']);
                            $dbrec->timemodified = backup_todb($info['GRADE_ITEM_HISTORY']['#']['TIMEMODIFIED']['0']['#']);
                            if ($oldobj = backup_getid($restore->backup_unique_code, "user", backup_todb($info['GRADE_ITEM_HISTORY']['#']['LOGGEDUSER']['0']['#']))) {
                                $dbrec->loggeduser = $oldobj->new_id;
                            }
                            $dbrec->courseid = $restore->course_id;
                            $oldobj = backup_getid($restore->backup_unique_code, 'grade_categories', backup_todb($info['GRADE_ITEM_HISTORY']['#']['CATEGORYID']['0']['#']));
                            $oldobj->categoryid = $category->new_id;
                            if (empty($oldobj->categoryid)) {
                                $counter++;
                                continue;
                                // category not restored
                            }
                            $dbrec->itemname = backup_todb($info['GRADE_ITEM_HISTORY']['#']['ITEMNAME']['0']['#']);
                            $dbrec->itemtype = backup_todb($info['GRADE_ITEM_HISTORY']['#']['ITEMTYPE']['0']['#']);
                            $dbrec->itemmodule = backup_todb($info['GRADE_ITEM_HISTORY']['#']['ITEMMODULE']['0']['#']);
                            // code from grade_items restore
                            $iteminstance = backup_todb($info['GRADE_ITEM_HISTORY']['#']['ITEMINSTANCE']['0']['#']);
                            // do not restore if this grade_item is a mod, and
                            if ($dbrec->itemtype == 'mod') {
                                if (!restore_userdata_selected($restore, $dbrec->itemmodule, $iteminstance)) {
                                    // module instance not selected when restored using granular
                                    // skip this item
                                    $counter++;
                                    continue;
                                }
                                // iteminstance should point to new mod
                                $mod = backup_getid($restore->backup_unique_code, $dbrec->itemmodule, $iteminstance);
                                $dbrec->iteminstance = $mod->new_id;
                            } else {
                                if ($dbrec->itemtype == 'category') {
                                    // the item instance should point to the new grade category
                                    // only proceed if we are restoring all grade items
                                    if ($restoreall) {
                                        $category = backup_getid($restore->backup_unique_code, 'grade_categories', $iteminstance);
                                        $dbrec->iteminstance = $category->new_id;
                                    } else {
                                        // otherwise we can safely ignore this grade item and subsequent
                                        // grade_raws, grade_finals etc
                                        continue;
                                    }
                                } elseif ($dbrec->itemtype == 'course') {
                                    // We don't restore course type to avoid duplicate course items
                                    if ($restoreall) {
                                        // TODO any special code needed here to restore course item without duplicating it?
                                        // find the course category with depth 1, and course id = current course id
                                        // this would have been already restored
                                        $cat = get_record('grade_categories', 'depth', 1, 'courseid', $restore->course_id);
                                        $dbrec->iteminstance = $cat->id;
                                    } else {
                                        $counter++;
                                        continue;
                                    }
                                }
                            }
                            $dbrec->itemnumber = backup_todb($info['GRADE_ITEM_HISTORY']['#']['ITEMNUMBER']['0']['#']);
                            $dbrec->iteminfo = backup_todb($info['GRADE_ITEM_HISTORY']['#']['ITEMINFO']['0']['#']);
                            $dbrec->idnumber = backup_todb($info['GRADE_ITEM_HISTORY']['#']['IDNUMBER']['0']['#']);
                            $dbrec->calculation = backup_todb($info['GRADE_ITEM_HISTORY']['#']['CALCULATION']['0']['#']);
                            $dbrec->gradetype = backup_todb($info['GRADE_ITEM_HISTORY']['#']['GRADETYPE']['0']['#']);
                            $dbrec->grademax = backup_todb($info['GRADE_ITEM_HISTORY']['#']['GRADEMAX']['0']['#']);
                            $dbrec->grademin = backup_todb($info['GRADE_ITEM_HISTORY']['#']['GRADEMIN']['0']['#']);
                            if ($oldobj = backup_getid($restore->backup_unique_code, "scale", backup_todb($info['GRADE_ITEM_HISTORY']['#']['SCALEID']['0']['#']))) {
                                // scaleid is optional
                                $dbrec->scaleid = $oldobj->new_id;
                            }
                            if ($oldobj = backup_getid($restore->backup_unique_code, "grade_outcomes", backup_todb($info['GRADE_ITEM_HISTORY']['#']['OUTCOMEID']['0']['#']))) {
                                // outcome is optional
                                $dbrec->outcomeid = $oldobj->new_id;
                            }
                            $dbrec->gradepass = backup_todb($info['GRADE_ITEM_HISTORY']['#']['GRADEPASS']['0']['#']);
                            $dbrec->multfactor = backup_todb($info['GRADE_ITEM_HISTORY']['#']['MULTFACTOR']['0']['#']);
                            $dbrec->plusfactor = backup_todb($info['GRADE_ITEM_HISTORY']['#']['PLUSFACTOR']['0']['#']);
                            $dbrec->aggregationcoef = backup_todb($info['GRADE_ITEM_HISTORY']['#']['AGGREGATIONCOEF']['0']['#']);
                            $dbrec->sortorder = backup_todb($info['GRADE_ITEM_HISTORY']['#']['SORTORDER']['0']['#']);
                            $dbrec->display = backup_todb($info['GRADE_ITEM_HISTORY']['#']['DISPLAY']['0']['#']);
                            $dbrec->decimals = backup_todb($info['GRADE_ITEM_HISTORY']['#']['DECIMALS']['0']['#']);
                            $dbrec->hidden = backup_todb($info['GRADE_ITEM_HISTORY']['#']['HIDDEN']['0']['#']);
                            $dbrec->locked = backup_todb($info['GRADE_ITEM_HISTORY']['#']['LOCKED']['0']['#']);
                            $dbrec->locktime = backup_todb($info['GRADE_ITEM_HISTORY']['#']['LOCKTIME']['0']['#']);
                            $dbrec->needsupdate = backup_todb($info['GRADE_ITEM_HISTORY']['#']['NEEDSUPDATE']['0']['#']);
                            insert_record('grade_items_history', $dbrec);
                            unset($dbrec);
                        }
                        //Increment counters
                        $counter++;
                        //Do some output
                        if ($counter % 1 == 0) {
                            if (!defined('RESTORE_SILENTLY')) {
                                echo ".";
                                if ($counter % 20 == 0) {
                                    echo "<br />";
                                }
                            }
                            backup_flush(300);
                        }
                    }
                }
            }
        }
        // process histories
        if ($gohcount && $status) {
            if (!defined('RESTORE_SILENTLY')) {
                echo '<li>' . get_string('gradeoutcomeshistory', 'grades') . '</li>';
            }
            $counter = 0;
            while ($counter < $gohcount) {
                //Fetch recordset_size records in each iteration
                $recs = get_records_select("backup_ids", "table_name = 'grade_outcomes_history' AND backup_code = '{$restore->backup_unique_code}'", "old_id", "old_id", $counter, $recordset_size);
                if ($recs) {
                    foreach ($recs as $rec) {
                        //Get the full record from backup_ids
                        $data = backup_getid($restore->backup_unique_code, 'grade_outcomes_history', $rec->old_id);
                        if ($data) {
                            //Now get completed xmlized object
                            $info = $data->info;
                            //traverse_xmlize($info);                            //Debug
                            //print_object ($GLOBALS['traverse_array']);         //Debug
                            //$GLOBALS['traverse_array']="";                     //Debug
                            $oldobj = backup_getid($restore->backup_unique_code, "grade_outcomes", backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['OLDID']['0']['#']));
                            if (empty($oldobj->new_id)) {
                                // if the old object is not being restored, can't restoring its history
                                $counter++;
                                continue;
                            }
                            $dbrec->oldid = $oldobj->new_id;
                            $dbrec->action = backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['ACTION']['0']['#']);
                            $dbrec->source = backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['SOURCE']['0']['#']);
                            $dbrec->timemodified = backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['TIMEMODIFIED']['0']['#']);
                            if ($oldobj = backup_getid($restore->backup_unique_code, "user", backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['LOGGEDUSER']['0']['#']))) {
                                $dbrec->loggeduser = $oldobj->new_id;
                            }
                            $dbrec->courseid = $restore->course_id;
                            $dbrec->shortname = backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['SHORTNAME']['0']['#']);
                            $dbrec->fullname = backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['FULLNAME']['0']['#']);
                            $oldobj = backup_getid($restore->backup_unique_code, "scale", backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['SCALEID']['0']['#']));
                            $dbrec->scaleid = $oldobj->new_id;
                            $dbrec->description = backup_todb($info['GRADE_OUTCOME_HISTORY']['#']['DESCRIPTION']['0']['#']);
                            insert_record('grade_outcomes_history', $dbrec);
                            unset($dbrec);
                        }
                        //Increment counters
                        $counter++;
                        //Do some output
                        if ($counter % 1 == 0) {
                            if (!defined('RESTORE_SILENTLY')) {
                                echo ".";
                                if ($counter % 20 == 0) {
                                    echo "<br />";
                                }
                            }
                            backup_flush(300);
                        }
                    }
                }
            }
        }
    }
    if (!defined('RESTORE_SILENTLY')) {
        //End ul
        echo '</ul>';
    }
    return $status;
}
예제 #27
0
 private function fill_table_recursive(&$element)
 {
     global $DB, $CFG;
     $type = $element['type'];
     $depth = $element['depth'];
     $grade_object = $element['object'];
     $eid = $grade_object->id;
     $element['userid'] = $this->user->id;
     $fullname = $this->gtree->get_element_header($element, true, true, true);
     $data = array();
     $hidden = '';
     $excluded = '';
     $class = '';
     $classfeedback = '';
     // If this is a hidden grade category, hide it completely from the user
     if ($type == 'category' && $grade_object->is_hidden() && !$this->canviewhidden && ($this->showhiddenitems == GRADE_REPORT_USER_HIDE_HIDDEN || $this->showhiddenitems == GRADE_REPORT_USER_HIDE_UNTIL && !$grade_object->is_hiddenuntil())) {
         return false;
     }
     if ($type == 'category') {
         $this->evenodd[$depth] = ($this->evenodd[$depth] + 1) % 2;
     }
     $alter = $this->evenodd[$depth] == 0 ? 'even' : 'odd';
     /// Process those items that have scores associated
     if ($type == 'item' or $type == 'categoryitem' or $type == 'courseitem') {
         $header_row = "row_{$eid}_{$this->user->id}";
         $header_cat = "cat_{$grade_object->categoryid}_{$this->user->id}";
         if (!($grade_grade = grade_grade::fetch(array('itemid' => $grade_object->id, 'userid' => $this->user->id)))) {
             $grade_grade = new grade_grade();
             $grade_grade->userid = $this->user->id;
             $grade_grade->itemid = $grade_object->id;
         }
         $grade_grade->load_grade_item();
         /// Hidden Items
         if ($grade_grade->grade_item->is_hidden()) {
             $hidden = ' dimmed_text';
         }
         $hide = false;
         // If this is a hidden grade item, hide it completely from the user.
         if ($grade_grade->is_hidden() && !$this->canviewhidden && ($this->showhiddenitems == GRADE_REPORT_USER_HIDE_HIDDEN || $this->showhiddenitems == GRADE_REPORT_USER_HIDE_UNTIL && !$grade_grade->is_hiddenuntil())) {
             $hide = true;
         } else {
             if (!empty($grade_object->itemmodule) && !empty($grade_object->iteminstance)) {
                 // The grade object can be marked visible but still be hidden if
                 // the student cannot see the activity due to conditional access
                 // and it's set to be hidden entirely.
                 $instances = $this->modinfo->get_instances_of($grade_object->itemmodule);
                 if (!empty($instances[$grade_object->iteminstance])) {
                     $cm = $instances[$grade_object->iteminstance];
                     if (!$cm->uservisible) {
                         // If there is 'availableinfo' text then it is only greyed
                         // out and not entirely hidden.
                         if (!$cm->availableinfo) {
                             $hide = true;
                         }
                     }
                 }
             }
         }
         if (!$hide) {
             /// Excluded Item
             if ($grade_grade->is_excluded()) {
                 $fullname .= ' [' . get_string('excluded', 'grades') . ']';
                 $excluded = ' excluded';
             }
             /// Other class information
             $class = "{$hidden} {$excluded}";
             if ($this->switch) {
                 // alter style based on whether aggregation is first or last
                 $class .= ($type == 'categoryitem' or $type == 'courseitem') ? " " . $alter . "d{$depth} baggt b2b" : " item b1b";
             } else {
                 $class .= ($type == 'categoryitem' or $type == 'courseitem') ? " " . $alter . "d{$depth} baggb" : " item b1b";
             }
             if ($type == 'categoryitem' or $type == 'courseitem') {
                 $header_cat = "cat_{$grade_object->iteminstance}_{$this->user->id}";
             }
             /// Name
             $data['itemname']['content'] = $fullname;
             $data['itemname']['class'] = $class;
             $data['itemname']['colspan'] = $this->maxdepth - $depth;
             $data['itemname']['celltype'] = 'th';
             $data['itemname']['id'] = $header_row;
             /// Actual Grade
             $gradeval = $grade_grade->finalgrade;
             if (!$this->canviewhidden) {
                 /// Virtual Grade (may be calculated excluding hidden items etc).
                 $adjustedgrade = $this->blank_hidden_total_and_adjust_bounds($this->courseid, $grade_grade->grade_item, $gradeval);
                 $gradeval = $adjustedgrade['grade'];
                 // We temporarily adjust the view of this grade item - because the min and
                 // max are affected by the hidden values in the aggregation.
                 $grade_grade->grade_item->grademax = $adjustedgrade['grademax'];
                 $grade_grade->grade_item->grademin = $adjustedgrade['grademin'];
             }
             if ($this->showfeedback) {
                 // Copy $class before appending itemcenter as feedback should not be centered
                 $classfeedback = $class;
             }
             $class .= " itemcenter ";
             if ($this->showweight) {
                 $data['weight']['class'] = $class;
                 $data['weight']['content'] = '-';
                 $data['weight']['headers'] = "{$header_cat} {$header_row} weight";
                 // has a weight assigned, might be extra credit
                 if ($grade_object->aggregationcoef > 0 && $type != 'courseitem') {
                     $data['weight']['content'] = number_format($grade_object->aggregationcoef, 2);
                 }
             }
             if ($this->showgrade) {
                 if ($grade_grade->grade_item->needsupdate) {
                     $data['grade']['class'] = $class . ' gradingerror';
                     $data['grade']['content'] = get_string('error');
                 } else {
                     if (!empty($CFG->grade_hiddenasdate) and $grade_grade->get_datesubmitted() and !$this->canviewhidden and $grade_grade->is_hidden() and !$grade_grade->grade_item->is_category_item() and !$grade_grade->grade_item->is_course_item()) {
                         // the problem here is that we do not have the time when grade value was modified, 'timemodified' is general modification date for grade_grades records
                         $class .= ' datesubmitted';
                         $data['grade']['class'] = $class;
                         $data['grade']['content'] = get_string('submittedon', 'grades', userdate($grade_grade->get_datesubmitted(), get_string('strftimedatetimeshort')));
                     } else {
                         if ($grade_grade->is_hidden()) {
                             $data['grade']['class'] = $class . ' dimmed_text';
                             $data['grade']['content'] = '-';
                             if ($this->canviewhidden) {
                                 $data['grade']['content'] = grade_format_gradevalue($gradeval, $grade_grade->grade_item, true);
                             }
                         } else {
                             $data['grade']['class'] = $class;
                             $data['grade']['content'] = grade_format_gradevalue($gradeval, $grade_grade->grade_item, true);
                         }
                     }
                 }
                 $data['grade']['headers'] = "{$header_cat} {$header_row} grade";
             }
             // Range
             if ($this->showrange) {
                 $data['range']['class'] = $class;
                 $data['range']['content'] = $grade_grade->grade_item->get_formatted_range(GRADE_DISPLAY_TYPE_REAL, $this->rangedecimals);
                 $data['range']['headers'] = "{$header_cat} {$header_row} range";
             }
             // Percentage
             if ($this->showpercentage) {
                 if ($grade_grade->grade_item->needsupdate) {
                     $data['percentage']['class'] = $class . ' gradingerror';
                     $data['percentage']['content'] = get_string('error');
                 } else {
                     if ($grade_grade->is_hidden()) {
                         $data['percentage']['class'] = $class . ' dimmed_text';
                         $data['percentage']['content'] = '-';
                         if ($this->canviewhidden) {
                             $data['percentage']['content'] = grade_format_gradevalue($gradeval, $grade_grade->grade_item, true, GRADE_DISPLAY_TYPE_PERCENTAGE);
                         }
                     } else {
                         $data['percentage']['class'] = $class;
                         $data['percentage']['content'] = grade_format_gradevalue($gradeval, $grade_grade->grade_item, true, GRADE_DISPLAY_TYPE_PERCENTAGE);
                     }
                 }
                 $data['percentage']['headers'] = "{$header_cat} {$header_row} percentage";
             }
             // Lettergrade
             if ($this->showlettergrade) {
                 if ($grade_grade->grade_item->needsupdate) {
                     $data['lettergrade']['class'] = $class . ' gradingerror';
                     $data['lettergrade']['content'] = get_string('error');
                 } else {
                     if ($grade_grade->is_hidden()) {
                         $data['lettergrade']['class'] = $class . ' dimmed_text';
                         if (!$this->canviewhidden) {
                             $data['lettergrade']['content'] = '-';
                         } else {
                             $data['lettergrade']['content'] = grade_format_gradevalue($gradeval, $grade_grade->grade_item, true, GRADE_DISPLAY_TYPE_LETTER);
                         }
                     } else {
                         $data['lettergrade']['class'] = $class;
                         $data['lettergrade']['content'] = grade_format_gradevalue($gradeval, $grade_grade->grade_item, true, GRADE_DISPLAY_TYPE_LETTER);
                     }
                 }
                 $data['lettergrade']['headers'] = "{$header_cat} {$header_row} lettergrade";
             }
             // Rank
             if ($this->showrank) {
                 if ($grade_grade->grade_item->needsupdate) {
                     $data['rank']['class'] = $class . ' gradingerror';
                     $data['rank']['content'] = get_string('error');
                 } elseif ($grade_grade->is_hidden()) {
                     $data['rank']['class'] = $class . ' dimmed_text';
                     $data['rank']['content'] = '-';
                 } else {
                     if (is_null($gradeval)) {
                         // no grade, no rank
                         $data['rank']['class'] = $class;
                         $data['rank']['content'] = '-';
                     } else {
                         /// find the number of users with a higher grade
                         $sql = "SELECT COUNT(DISTINCT(userid))\n                                  FROM {grade_grades}\n                                 WHERE finalgrade > ?\n                                       AND itemid = ?\n                                       AND hidden = 0";
                         $rank = $DB->count_records_sql($sql, array($grade_grade->finalgrade, $grade_grade->grade_item->id)) + 1;
                         $data['rank']['class'] = $class;
                         $data['rank']['content'] = "{$rank}/" . $this->get_numusers(false);
                         // total course users
                     }
                 }
                 $data['rank']['headers'] = "{$header_cat} {$header_row} rank";
             }
             // Average
             if ($this->showaverage) {
                 $data['average']['class'] = $class;
                 if (!empty($this->gtree->items[$eid]->avg)) {
                     $data['average']['content'] = $this->gtree->items[$eid]->avg;
                 } else {
                     $data['average']['content'] = '-';
                 }
                 $data['average']['headers'] = "{$header_cat} {$header_row} average";
             }
             // Feedback
             if ($this->showfeedback) {
                 if ($grade_grade->overridden > 0 and ($type == 'categoryitem' or $type == 'courseitem')) {
                     $data['feedback']['class'] = $classfeedback . ' feedbacktext';
                     $data['feedback']['content'] = get_string('overridden', 'grades') . ': ' . format_text($grade_grade->feedback, $grade_grade->feedbackformat);
                 } else {
                     if (empty($grade_grade->feedback) or !$this->canviewhidden and $grade_grade->is_hidden()) {
                         $data['feedback']['class'] = $classfeedback . ' feedbacktext';
                         $data['feedback']['content'] = '&nbsp;';
                     } else {
                         $data['feedback']['class'] = $classfeedback . ' feedbacktext';
                         $data['feedback']['content'] = format_text($grade_grade->feedback, $grade_grade->feedbackformat);
                     }
                 }
                 $data['feedback']['headers'] = "{$header_cat} {$header_row} feedback";
             }
         }
     }
     /// Category
     if ($type == 'category') {
         $data['leader']['class'] = $class . ' ' . $alter . "d{$depth} b1t b2b b1l";
         $data['leader']['rowspan'] = $element['rowspan'];
         if ($this->switch) {
             // alter style based on whether aggregation is first or last
             $data['itemname']['class'] = $class . ' ' . $alter . "d{$depth} b1b b1t";
         } else {
             $data['itemname']['class'] = $class . ' ' . $alter . "d{$depth} b2t";
         }
         $data['itemname']['colspan'] = $this->maxdepth - $depth + count($this->tablecolumns) - 1;
         $data['itemname']['content'] = $fullname;
         $data['itemname']['celltype'] = 'th';
         $data['itemname']['id'] = "cat_{$grade_object->id}_{$this->user->id}";
     }
     /// Add this row to the overall system
     $this->tabledata[] = $data;
     /// Recursively iterate through all child elements
     if (isset($element['children'])) {
         foreach ($element['children'] as $key => $child) {
             $this->fill_table_recursive($element['children'][$key]);
         }
     }
 }
예제 #28
0
/**
 * Grading cron job. Performs background clean up on the gradebook
 */
function grade_cron()
{
    global $CFG, $DB;
    $now = time();
    $sql = "SELECT i.*\n              FROM {grade_items} i\n             WHERE i.locked = 0 AND i.locktime > 0 AND i.locktime < ? AND EXISTS (\n                SELECT 'x' FROM {grade_items} c WHERE c.itemtype='course' AND c.needsupdate=0 AND c.courseid=i.courseid)";
    // go through all courses that have proper final grades and lock them if needed
    $rs = $DB->get_recordset_sql($sql, array($now));
    foreach ($rs as $item) {
        $grade_item = new grade_item($item, false);
        $grade_item->locked = $now;
        $grade_item->update('locktime');
    }
    $rs->close();
    $grade_inst = new grade_grade();
    $fields = 'g.' . implode(',g.', $grade_inst->required_fields);
    $sql = "SELECT {$fields}\n              FROM {grade_grades} g, {grade_items} i\n             WHERE g.locked = 0 AND g.locktime > 0 AND g.locktime < ? AND g.itemid=i.id AND EXISTS (\n                SELECT 'x' FROM {grade_items} c WHERE c.itemtype='course' AND c.needsupdate=0 AND c.courseid=i.courseid)";
    // go through all courses that have proper final grades and lock them if needed
    $rs = $DB->get_recordset_sql($sql, array($now));
    foreach ($rs as $grade) {
        $grade_grade = new grade_grade($grade, false);
        $grade_grade->locked = $now;
        $grade_grade->update('locktime');
    }
    $rs->close();
    //TODO: do not run this cleanup every cron invocation
    // cleanup history tables
    if (!empty($CFG->gradehistorylifetime)) {
        // value in days
        $histlifetime = $now - $CFG->gradehistorylifetime * 3600 * 24;
        $tables = array('grade_outcomes_history', 'grade_categories_history', 'grade_items_history', 'grade_grades_history', 'scale_history');
        foreach ($tables as $table) {
            if ($DB->delete_records_select($table, "timemodified < ?", array($histlifetime))) {
                mtrace("    Deleted old grade history records from '{$table}'");
            }
        }
    }
}
예제 #29
0
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;
    }
}
예제 #30
0
 protected function sub_test_update_final_grade()
 {
     // MDL-31713 Check that min and max are set on the grade_grade instance
     // if the grade is overridden before the activity has supplied a grade.
     $min = 2;
     $max = 8;
     // Create a brand new grade item.
     $grade_item = new grade_item();
     $this->assertTrue(method_exists($grade_item, 'insert'));
     $grade_item->courseid = $this->courseid;
     $grade_item->categoryid = $this->grade_categories[1]->id;
     $grade_item->itemname = 'brand new unit test grade item';
     $grade_item->itemtype = 'mod';
     $grade_item->itemmodule = 'quiz';
     $grade_item->iteminfo = 'Grade item used for unit testing';
     $grade_item->grademin = $min;
     $grade_item->grademax = $max;
     $grade_item->insert();
     // Override the student grade.
     $grade_item->update_final_grade($this->user[1]->id, 7, 'gradebook', '', FORMAT_MOODLE);
     // Check the student's grade has the correct min and max grade.
     $grade_grade = grade_grade::fetch(array('userid' => $this->user[1]->id, 'itemid' => $grade_item->id));
     $this->assertEquals($min, $grade_grade->rawgrademin);
     $this->assertEquals($max, $grade_grade->rawgrademax);
 }