function definition_after_data()
 {
     global $CFG, $COURSE;
     $mform =& $this->_form;
     if ($id = $mform->getElementValue('id')) {
         $grade_item = grade_item::fetch(array('id' => $id));
         //remove the aggregation coef element if not needed
         if ($grade_item->is_course_item()) {
             $mform->removeElement('aggregationcoef');
         } else {
             if ($grade_item->is_category_item()) {
                 $category = $grade_item->get_item_category();
                 $parent_category = $category->get_parent_category();
                 if (!$parent_category->is_aggregationcoef_used()) {
                     $mform->removeElement('aggregationcoef');
                 }
             } else {
                 $parent_category = $grade_item->get_parent_category();
                 if (!$parent_category->is_aggregationcoef_used()) {
                     $mform->removeElement('aggregationcoef');
                 }
             }
         }
     } else {
         $course_category = grade_category::fetch_course_category($COURSE->id);
         if (!$course_category->is_aggregationcoef_used()) {
             $mform->removeElement('aggregationcoef');
         }
     }
 }
Exemple #2
0
 function fill_table()
 {
     global $CFG;
     $numusers = $this->get_numusers();
     if ($courses = get_courses('all', null, 'c.id, c.shortname')) {
         foreach ($courses as $course) {
             // Get course grade_item
             $grade_item = grade_item::fetch(array('itemtype' => 'course', 'courseid' => $course->id));
             // Get the grade
             $finalgrade = get_field('grade_grades', 'finalgrade', 'itemid', $grade_item->id, 'userid', $this->user->id);
             /// prints rank
             if ($finalgrade) {
                 /// find the number of users with a higher grade
                 $sql = "SELECT COUNT(DISTINCT(userid))\n                            FROM {$CFG->prefix}grade_grades\n                            WHERE finalgrade > {$finalgrade}\n                            AND itemid = {$grade_item->id}";
                 $rank = count_records_sql($sql) + 1;
                 $rankdata = "{$rank}/{$numusers}";
             } else {
                 // no grade, no rank
                 $rankdata = "-";
             }
             $courselink = '<a href="' . $CFG->wwwroot . '/grade/report/user/index.php?id=' . $course->id . '">' . $course->shortname . '</a>';
             $this->table->add_data(array($courselink, round(grade_to_percentage($finalgrade, $grade_item->grademin, $grade_item->grademax), 1) . '%', $rankdata));
         }
         return true;
     } else {
         notify(get_string('nocourses', 'grades'));
         return false;
     }
 }
 /**
  * Tests the backup and restore of single activity to same course (duplicate)
  * when it contains fields and views.
  */
 public function test_duplicate()
 {
     global $DB, $CFG;
     $this->resetAfterTest(true);
     $this->setAdminUser();
     $generator = $this->getDataGenerator();
     $dataformgenerator = $generator->get_plugin_generator('mod_dataform');
     // Create a course.
     $course = $generator->create_course();
     // DATAFORM 1.
     $params = array('course' => $course->id, 'grade' => 100);
     $dataform1 = $dataformgenerator->create_instance($params);
     $df1 = mod_dataform_dataform::instance($dataform1->id);
     // Add fields.
     $fieldtypes = array_keys(core_component::get_plugin_list('dataformfield'));
     $fieldtypescount = count($fieldtypes);
     foreach ($fieldtypes as $type) {
         $df1->field_manager->add_field($type);
     }
     // Add views.
     $viewtypes = array_keys(core_component::get_plugin_list('dataformview'));
     $viewtypescount = count($viewtypes);
     foreach ($viewtypes as $type) {
         $df1->view_manager->add_view($type);
     }
     // Fetch the grade item.
     $params = array('itemtype' => 'mod', 'itemmodule' => 'dataform', 'iteminstance' => $dataform1->id, 'courseid' => $course->id, 'itemnumber' => 0);
     $gradeitem1 = grade_item::fetch($params);
     // Check number of dataforms.
     $this->assertEquals(1, $DB->count_records('dataform'));
     // Check number of fields.
     $this->assertEquals($fieldtypescount, $DB->count_records('dataform_fields'));
     $this->assertEquals($fieldtypescount, $DB->count_records('dataform_fields', array('dataid' => $dataform1->id)));
     // Check number of views.
     $this->assertEquals($viewtypescount, $DB->count_records('dataform_views'));
     $this->assertEquals($viewtypescount, $DB->count_records('dataform_views', array('dataid' => $dataform1->id)));
     // Check number of filters.
     // $this->assertEquals(2, $DB->count_records('dataform_filters'));
     // $this->assertEquals(2, $DB->count_records('dataform_filters', array('dataid' => $dataform1->id)));.
     // DUPLICATE the dataform instance.
     $dataform2 = $dataformgenerator->duplicate_instance($course, $dataform1->cmid);
     // Check number of dataforms.
     $this->assertEquals(2, $DB->count_records('dataform'));
     // Check duplication of fields.
     $this->assertEquals($fieldtypescount * 2, $DB->count_records('dataform_fields'));
     $this->assertEquals($fieldtypescount, $DB->count_records('dataform_fields', array('dataid' => $dataform1->id)));
     $this->assertEquals($fieldtypescount, $DB->count_records('dataform_fields', array('dataid' => $dataform2->id)));
     // Check duplication of views.
     $this->assertEquals($viewtypescount * 2, $DB->count_records('dataform_views'));
     $this->assertEquals($viewtypescount, $DB->count_records('dataform_views', array('dataid' => $dataform1->id)));
     $this->assertEquals($viewtypescount, $DB->count_records('dataform_views', array('dataid' => $dataform2->id)));
     // Check number of filters.
     // $this->assertEquals(4, $DB->count_records('dataform_filters');
     // $this->assertEquals(2, $DB->count_records('dataform_filters', array('dataid' => $dataform1->id));
     // $this->assertEquals(2, $DB->count_records('dataform_filters', array('dataid' => $dataform2->id));.
     // Dataform cleanup.
     $dataformgenerator->delete_all_instances();
 }
 /**
  * Tests grade_report_grader::process_data()
  *
  * process_data() processes submitted grade and feedback data
  */
 public function test_process_data()
 {
     global $DB, $CFG;
     $this->resetAfterTest(true);
     $course = $this->getDataGenerator()->create_course();
     // Create and enrol a student.
     $student = $this->getDataGenerator()->create_user(array('username' => 'Student Sam'));
     $role = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST);
     $this->getDataGenerator()->enrol_user($student->id, $course->id, $role->id);
     // Test with limited grades.
     $CFG->unlimitedgrades = 0;
     $forummax = 80;
     $forum1 = $this->getDataGenerator()->create_module('forum', array('assessed' => 1, 'scale' => $forummax, 'course' => $course->id));
     // Switch the stdClass instance for a grade item instance.
     $forum1 = grade_item::fetch(array('itemtype' => 'mod', 'itemmodule' => 'forum', 'iteminstance' => $forum1->id, 'courseid' => $course->id));
     $report = $this->create_report($course);
     $testgrade = 60.0;
     $data = new stdClass();
     $data->id = $course->id;
     $data->report = 'grader';
     $data->timepageload = time();
     $data->grade = array();
     $data->grade[$student->id] = array();
     $data->grade[$student->id][$forum1->id] = $testgrade;
     $warnings = $report->process_data($data);
     $this->assertEquals(count($warnings), 0);
     $studentgrade = grade_grade::fetch(array('itemid' => $forum1->id, '' => $student->id));
     $this->assertEquals($studentgrade->finalgrade, $testgrade);
     // Grade above max. Should be pulled down to max.
     $toobig = 200.0;
     $data->grade[$student->id][$forum1->id] = $toobig;
     $data->timepageload = time();
     $warnings = $report->process_data($data);
     $this->assertEquals(count($warnings), 1);
     $studentgrade = grade_grade::fetch(array('itemid' => $forum1->id, '' => $student->id));
     $this->assertEquals($studentgrade->finalgrade, $forummax);
     // Grade below min. Should be pulled up to min.
     $toosmall = -10.0;
     $data->grade[$student->id][$forum1->id] = $toosmall;
     $data->timepageload = time();
     $warnings = $report->process_data($data);
     $this->assertEquals(count($warnings), 1);
     $studentgrade = grade_grade::fetch(array('itemid' => $forum1->id, '' => $student->id));
     $this->assertEquals($studentgrade->finalgrade, 0);
     // Test unlimited grades so we can give a student a grade about max.
     $CFG->unlimitedgrades = 1;
     $data->grade[$student->id][$forum1->id] = $toobig;
     $data->timepageload = time();
     $warnings = $report->process_data($data);
     $this->assertEquals(count($warnings), 0);
     $studentgrade = grade_grade::fetch(array('itemid' => $forum1->id, '' => $student->id));
     $this->assertEquals($studentgrade->finalgrade, $toobig);
 }
 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);
     }
 }
Exemple #6
0
 public function test_grade_edit_tree_column_range_get_item_cell()
 {
     global $DB, $CFG;
     $this->resetAfterTest(true);
     // Make some things we need.
     $scale = $this->getDataGenerator()->create_scale();
     $course = $this->getDataGenerator()->create_course();
     $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
     $modulecontext = context_module::instance($assign->id);
     // The generator returns a dummy object, lets get the real assign object.
     $assign = new assign($modulecontext, false, false);
     $cm = $assign->get_course_module();
     // Get range column.
     $column = grade_edit_tree_column::factory('range');
     $gradeitemparams = array('itemtype' => 'mod', 'itemmodule' => $cm->modname, 'iteminstance' => $cm->instance, 'courseid' => $cm->course, 'itemnumber' => 0);
     // Lets set the grade to something we know.
     $instance = $assign->get_instance();
     $instance->grade = 70;
     $instance->instance = $instance->id;
     $assign->update_instance($instance);
     $gradeitem = grade_item::fetch($gradeitemparams);
     $cell = $column->get_item_cell($gradeitem, array());
     $this->assertEquals(GRADE_TYPE_VALUE, $gradeitem->gradetype);
     $this->assertEquals(null, $gradeitem->scaleid);
     $this->assertEquals(70.0, (double) $cell->text, "Grade text is 70", 0.01);
     // Now change it to a scale.
     $instance = $assign->get_instance();
     $instance->grade = -$scale->id;
     $instance->instance = $instance->id;
     $assign->update_instance($instance);
     $gradeitem = grade_item::fetch($gradeitemparams);
     $cell = $column->get_item_cell($gradeitem, array());
     // Make the expected scale text.
     $scaleitems = null;
     $scaleitems = explode(',', $scale->scale);
     $scalestring = end($scaleitems) . ' (' . count($scaleitems) . ')';
     $this->assertEquals(GRADE_TYPE_SCALE, $gradeitem->gradetype);
     $this->assertEquals($scale->id, $gradeitem->scaleid);
     $this->assertEquals($scalestring, $cell->text, "Grade text matches scale");
     // Now change it to no grade.
     $instance = $assign->get_instance();
     $instance->grade = 0;
     $instance->instance = $instance->id;
     $assign->update_instance($instance);
     $gradeitem = grade_item::fetch($gradeitemparams);
     $cell = $column->get_item_cell($gradeitem, array());
     $this->assertEquals(GRADE_TYPE_TEXT, $gradeitem->gradetype);
     $this->assertEquals(null, $gradeitem->scaleid);
     $this->assertEquals(' - ', $cell->text, 'Grade text matches empty value of " - "');
 }
Exemple #7
0
 function validation($data, $files)
 {
     $errors = parent::validation($data, $files);
     $mform =& $this->_form;
     // check the calculation formula
     if ($data['calculation'] != '') {
         $grade_item = grade_item::fetch(array('id' => $data['id'], 'courseid' => $data['courseid']));
         $calculation = calc_formula::unlocalize(stripslashes($data['calculation']));
         $result = $grade_item->validate_formula($calculation);
         if ($result !== true) {
             $errors['calculation'] = $result;
         }
     }
     return $errors;
 }
 function validation($data)
 {
     $errors = array();
     $mform =& $this->_form;
     // check the calculation formula
     if ($data['calculation'] != '') {
         $grade_item = grade_item::fetch(array('id' => $data['id'], 'courseid' => $data['courseid']));
         $calculation = calc_formula::unlocalize(stripslashes($data['calculation']));
         $result = $grade_item->validate_formula($calculation);
         if ($result !== true) {
             $errors['calculation'] = $result;
         }
     }
     if (0 == count($errors)) {
         return true;
     } else {
         return $errors;
     }
 }
 /**
  * Updates activity completion status.
  *
  * @return void
  */
 public static function update_require_specific_grade(\core\event\base $event)
 {
     global $DB;
     $entryuserid = $event->relateduserid;
     $giid = $event->other['itemid'];
     if (!($gitem = \grade_item::fetch(array('id' => $giid, 'itemmodule' => 'dataform')))) {
         return;
     }
     $dataformid = $gitem->iteminstance;
     $df = \mod_dataform_dataform::instance($dataformid);
     // Currently only completion by require entries.
     if ($df->completionspecificgrade) {
         $completion = new \completion_info($df->course);
         if ($completion->is_enabled($df->cm) != COMPLETION_TRACKING_AUTOMATIC) {
             return;
         }
         $completion->update_state($df->cm, COMPLETION_UNKNOWN, $entryuserid);
     }
 }
 /**
  * Adds a grade category and moves the specified item into it.
  * Uses locks to prevent race conditions (see MDL-37055).
  */
 public function execute()
 {
     $customdata = $this->get_custom_data();
     // Get lock timeout.
     $timeout = 5;
     // A namespace for the locks.
     $locktype = 'block_mhaairs_add_category';
     // Resource key - course id and category name.
     $resource = "course: {$customdata->courseid}; catname: {$customdata->catname}";
     // Get an instance of the currently configured lock_factory.
     $lockfactory = \core\lock\lock_config::get_lock_factory($locktype);
     // Open a lock.
     $lock = $lockfactory->get_lock($resource, $timeout);
     // Add the category.
     $catparams = array('fullname' => $customdata->catname, 'courseid' => $customdata->courseid);
     if (!($category = \grade_category::fetch($catparams))) {
         // If the category does not exist we create it.
         $gradeaggregation = get_config('core', 'grade_aggregation');
         if ($gradeaggregation === false) {
             $gradeaggregation = GRADE_AGGREGATE_WEIGHTED_MEAN2;
         }
         // Parent category is automatically added(created) during insert.
         $catparams['hidden'] = false;
         $catparams['aggregation'] = $gradeaggregation;
         try {
             $category = new \grade_category($catparams, false);
             $category->id = $category->insert();
         } catch (Exception $e) {
             // Must release the locks.
             $lock->release();
             // Rethrow to reschedule task.
             throw $e;
         }
     }
     // Release locks.
     $lock->release();
     // Add the item to the category.
     $gitem = \grade_item::fetch(array('id' => $customdata->itemid));
     $gitem->categoryid = $category->id;
     $gitem->update();
 }
 /**
  * Tests the event details.
  */
 public function test_event()
 {
     global $CFG;
     require_once "{$CFG->libdir}/gradelib.php";
     $this->resetAfterTest();
     $course = $this->getDataGenerator()->create_course();
     $user = $this->getDataGenerator()->create_user();
     $quiz = $this->getDataGenerator()->create_module('quiz', array('course' => $course->id));
     // Create a grade item for the quiz.
     $grade = array();
     $grade['userid'] = $user->id;
     $grade['rawgrade'] = 50;
     grade_update('mod/quiz', $course->id, 'mod', 'quiz', $quiz->id, 0, $grade);
     // Get the grade item and override it.
     $gradeitem = grade_item::fetch(array('itemtype' => 'mod', 'itemmodule' => 'quiz', 'iteminstance' => $quiz->id, 'courseid' => $course->id));
     $gradeitem->update_final_grade($user->id, 10, 'gradebook');
     // Get the grade_grade object.
     $gradegrade = new grade_grade(array('userid' => $user->id, 'itemid' => $gradeitem->id), true);
     $gradegrade->grade_item = $gradeitem;
     // Trigger the event.
     $sink = $this->redirectEvents();
     course_delete_module($quiz->cmid);
     $events = $sink->get_events();
     $event = reset($events);
     $sink->close();
     // Check the event details are correct.
     $grade = $event->get_grade();
     $this->assertInstanceOf('grade_grade', $grade);
     $this->assertInstanceOf('\\core\\event\\grade_deleted', $event);
     $this->assertEquals(context_course::instance($course->id), $event->get_context());
     $this->assertSame($event->objecttable, 'grade_grades');
     $this->assertEquals($event->objectid, $gradegrade->id);
     $this->assertEquals($event->other['itemid'], $gradeitem->id);
     $this->assertTrue($event->other['overridden']);
     $this->assertEquals(10, $event->other['finalgrade']);
     $this->assertEventContextNotUsed($event);
     $this->assertEquals($gradegrade->id, $grade->id);
 }
/**
 * Returns grading information for given activity, optionally with user grades
 * Manual, course or category items can not be queried.
 *
 * @category grade
 * @param int    $courseid ID of course
 * @param string $itemtype Type of grade item. For example, 'mod' or 'block'
 * @param string $itemmodule More specific then $itemtype. For example, 'forum' or 'quiz'. May be NULL for some item types
 * @param int    $iteminstance ID of the item module
 * @param mixed  $userid_or_ids Either a single user ID, an array of user IDs or null. If user ID or IDs are not supplied returns information about grade_item
 * @return array Array of grade information objects (scaleid, name, grade and locked status, etc.) indexed with itemnumbers
 */
function grade_get_grades($courseid, $itemtype, $itemmodule, $iteminstance, $userid_or_ids = null)
{
    global $CFG;
    $return = new stdClass();
    $return->items = array();
    $return->outcomes = array();
    $course_item = grade_item::fetch_course_item($courseid);
    $needsupdate = array();
    if ($course_item->needsupdate) {
        $result = grade_regrade_final_grades($courseid);
        if ($result !== true) {
            $needsupdate = array_keys($result);
        }
    }
    if ($grade_items = grade_item::fetch_all(array('itemtype' => $itemtype, 'itemmodule' => $itemmodule, 'iteminstance' => $iteminstance, 'courseid' => $courseid))) {
        foreach ($grade_items as $grade_item) {
            $decimalpoints = null;
            if (empty($grade_item->outcomeid)) {
                // prepare information about grade item
                $item = new stdClass();
                $item->itemnumber = $grade_item->itemnumber;
                $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();
                $item->grades = array();
                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;
                }
                if (empty($userid_or_ids)) {
                    $userids = array();
                } else {
                    if (is_array($userid_or_ids)) {
                        $userids = $userid_or_ids;
                    } else {
                        $userids = array($userid_or_ids);
                    }
                }
                if ($userids) {
                    $grade_grades = grade_grade::fetch_users_grades($grade_item, $userids, true);
                    foreach ($userids as $userid) {
                        $grade_grades[$userid]->grade_item =& $grade_item;
                        $grade = new stdClass();
                        $grade->grade = $grade_grades[$userid]->finalgrade;
                        $grade->locked = $grade_grades[$userid]->is_locked();
                        $grade->hidden = $grade_grades[$userid]->is_hidden();
                        $grade->overridden = $grade_grades[$userid]->overridden;
                        $grade->feedback = $grade_grades[$userid]->feedback;
                        $grade->feedbackformat = $grade_grades[$userid]->feedbackformat;
                        $grade->usermodified = $grade_grades[$userid]->usermodified;
                        $grade->datesubmitted = $grade_grades[$userid]->get_datesubmitted();
                        $grade->dategraded = $grade_grades[$userid]->get_dategraded();
                        // create text representation of grade
                        if ($grade_item->gradetype == GRADE_TYPE_TEXT or $grade_item->gradetype == GRADE_TYPE_NONE) {
                            $grade->grade = null;
                            $grade->str_grade = '-';
                            $grade->str_long_grade = $grade->str_grade;
                        } else {
                            if (in_array($grade_item->id, $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);
                        }
                        $item->grades[$userid] = $grade;
                    }
                }
                $return->items[$grade_item->itemnumber] = $item;
            } else {
                if (!($grade_outcome = grade_outcome::fetch(array('id' => $grade_item->outcomeid)))) {
                    debugging('Incorect outcomeid found');
                    continue;
                }
                // outcome info
                $outcome = new stdClass();
                $outcome->itemnumber = $grade_item->itemnumber;
                $outcome->scaleid = $grade_outcome->scaleid;
                $outcome->name = $grade_outcome->get_name();
                $outcome->locked = $grade_item->is_locked();
                $outcome->hidden = $grade_item->is_hidden();
                if (empty($userid_or_ids)) {
                    $userids = array();
                } else {
                    if (is_array($userid_or_ids)) {
                        $userids = $userid_or_ids;
                    } else {
                        $userids = array($userid_or_ids);
                    }
                }
                if ($userids) {
                    $grade_grades = grade_grade::fetch_users_grades($grade_item, $userids, true);
                    foreach ($userids as $userid) {
                        $grade_grades[$userid]->grade_item =& $grade_item;
                        $grade = new stdClass();
                        $grade->grade = $grade_grades[$userid]->finalgrade;
                        $grade->locked = $grade_grades[$userid]->is_locked();
                        $grade->hidden = $grade_grades[$userid]->is_hidden();
                        $grade->feedback = $grade_grades[$userid]->feedback;
                        $grade->feedbackformat = $grade_grades[$userid]->feedbackformat;
                        $grade->usermodified = $grade_grades[$userid]->usermodified;
                        // create text representation of grade
                        if (in_array($grade_item->id, $needsupdate)) {
                            $grade->grade = false;
                            $grade->str_grade = get_string('error');
                        } else {
                            if (is_null($grade->grade)) {
                                $grade->grade = 0;
                                $grade->str_grade = get_string('nooutcome', 'grades');
                            } else {
                                $grade->grade = (int) $grade->grade;
                                $scale = $grade_item->load_scale();
                                $grade->str_grade = format_string($scale->scale_items[(int) $grade->grade - 1]);
                            }
                        }
                        // create html representation of feedback
                        if (is_null($grade->feedback)) {
                            $grade->str_feedback = '';
                        } else {
                            $grade->str_feedback = format_text($grade->feedback, $grade->feedbackformat);
                        }
                        $outcome->grades[$userid] = $grade;
                    }
                }
                if (isset($return->outcomes[$grade_item->itemnumber])) {
                    // itemnumber duplicates - lets fix them!
                    $newnumber = $grade_item->itemnumber + 1;
                    while (grade_item::fetch(array('itemtype' => $itemtype, 'itemmodule' => $itemmodule, 'iteminstance' => $iteminstance, 'courseid' => $courseid, 'itemnumber' => $newnumber))) {
                        $newnumber++;
                    }
                    $outcome->itemnumber = $newnumber;
                    $grade_item->itemnumber = $newnumber;
                    $grade_item->update('system');
                }
                $return->outcomes[$grade_item->itemnumber] = $outcome;
            }
        }
    }
    // sort results using itemnumbers
    ksort($return->items, SORT_NUMERIC);
    ksort($return->outcomes, SORT_NUMERIC);
    return $return;
}
 /**
  * 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;
 }
 /**
  * Test get_attempt_access_information
  */
 public function test_get_attempt_access_information()
 {
     global $DB;
     // Create a new quiz with attempts.
     $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz');
     $data = array('course' => $this->course->id, 'sumgrades' => 2);
     $quiz = $quizgenerator->create_instance($data);
     // Create some questions.
     $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
     $cat = $questiongenerator->create_question_category();
     $question = $questiongenerator->create_question('numerical', null, array('category' => $cat->id));
     quiz_add_quiz_question($question->id, $quiz);
     $question = $questiongenerator->create_question('shortanswer', null, array('category' => $cat->id));
     quiz_add_quiz_question($question->id, $quiz);
     // Add new question types in the category (for the random one).
     $question = $questiongenerator->create_question('truefalse', null, array('category' => $cat->id));
     $question = $questiongenerator->create_question('essay', null, array('category' => $cat->id));
     $question = $questiongenerator->create_question('random', null, array('category' => $cat->id));
     quiz_add_quiz_question($question->id, $quiz);
     $quizobj = quiz::create($quiz->id, $this->student->id);
     // Set grade to pass.
     $item = grade_item::fetch(array('courseid' => $this->course->id, 'itemtype' => 'mod', 'itemmodule' => 'quiz', 'iteminstance' => $quiz->id, 'outcomeid' => null));
     $item->gradepass = 80;
     $item->update();
     $this->setUser($this->student);
     // Default restrictions (none).
     $result = mod_quiz_external::get_attempt_access_information($quiz->id);
     $result = external_api::clean_returnvalue(mod_quiz_external::get_attempt_access_information_returns(), $result);
     $expected = array('isfinished' => false, 'preventnewattemptreasons' => [], 'warnings' => []);
     $this->assertEquals($expected, $result);
     // Limited attempts.
     $quiz->attempts = 1;
     $DB->update_record('quiz', $quiz);
     // Now, do one attempt.
     $quba = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context());
     $quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour);
     $timenow = time();
     $attempt = quiz_create_attempt($quizobj, 1, false, $timenow, false, $this->student->id);
     quiz_start_new_attempt($quizobj, $quba, $attempt, 1, $timenow);
     quiz_attempt_save_started($quizobj, $quba, $attempt);
     // Process some responses from the student.
     $attemptobj = quiz_attempt::create($attempt->id);
     $tosubmit = array(1 => array('answer' => '3.14'));
     $attemptobj->process_submitted_actions($timenow, false, $tosubmit);
     // Finish the attempt.
     $attemptobj = quiz_attempt::create($attempt->id);
     $this->assertTrue($attemptobj->has_response_to_at_least_one_graded_question());
     $attemptobj->process_finish($timenow, false);
     // Can we start a new attempt? We shall not!
     $result = mod_quiz_external::get_attempt_access_information($quiz->id, $attempt->id);
     $result = external_api::clean_returnvalue(mod_quiz_external::get_attempt_access_information_returns(), $result);
     // Now new attemps allowed.
     $this->assertCount(1, $result['preventnewattemptreasons']);
     $this->assertFalse($result['ispreflightcheckrequired']);
     $this->assertEquals(get_string('nomoreattempts', 'quiz'), $result['preventnewattemptreasons'][0]);
 }
Exemple #15
0
/**
 * This function migrades all the pre 1.9 gradebook data from xml
 */
function restore_migrate_old_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;
    }
    // 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
    $importing = !empty($SESSION->restore->importing);
    // there should not be a way to import old backups, but anyway ;-)
    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
        if (count($prev_grade_items) > 1 or count($prev_grade_cats) > 1) {
            $restoreall = false;
        }
        unset($prev_grade_items);
        unset($prev_grade_cats);
    }
    // force creation of all grade_items - the course_modules already exist
    grade_force_full_regrading($restore->course_id);
    grade_grab_course_grades($restore->course_id);
    // Start ul
    if (!defined('RESTORE_SILENTLY')) {
        echo '<ul>';
    }
    /// 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_letter' 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_letter', $rec->old_id);
                if ($data) {
                    $info = $data->info;
                    $dbrec = new object();
                    $dbrec->contextid = $context->id;
                    $dbrec->lowerboundary = backup_todb($info['GRADE_LETTER']['#']['GRADE_LOW']['0']['#']);
                    $dbrec->letter = backup_todb($info['GRADE_LETTER']['#']['LETTER']['0']['#']);
                    insert_record('grade_letters', $dbrec);
                }
            }
        }
    }
    if (!defined('RESTORE_SILENTLY')) {
        echo '<li>' . get_string('categories', 'grades') . '</li>';
    }
    //Fetch recordset_size records in each iteration
    $recs = get_records_select("backup_ids", "table_name = 'grade_category' AND backup_code = {$restore->backup_unique_code}", "old_id", "old_id");
    $cat_count = count($recs);
    if ($recs) {
        foreach ($recs as $rec) {
            //Get the full record from backup_ids
            $data = backup_getid($restore->backup_unique_code, 'grade_category', $rec->old_id);
            if ($data) {
                //Now get completed xmlized object
                $info = $data->info;
                if ($restoreall) {
                    if ($cat_count == 1) {
                        $course_category->fullname = backup_todb($info['GRADE_CATEGORY']['#']['NAME']['0']['#'], false);
                        $course_category->droplow = backup_todb($info['GRADE_CATEGORY']['#']['DROP_X_LOWEST']['0']['#'], false);
                        $course_category->aggregation = GRADE_AGGREGATE_WEIGHTED_MEAN2;
                        $course_category->aggregateonlygraded = 0;
                        $course_category->update('restore');
                        $grade_category = $course_category;
                    } else {
                        $grade_category = new grade_category();
                        $grade_category->courseid = $restore->course_id;
                        $grade_category->fullname = backup_todb($info['GRADE_CATEGORY']['#']['NAME']['0']['#'], false);
                        $grade_category->droplow = backup_todb($info['GRADE_CATEGORY']['#']['DROP_X_LOWEST']['0']['#'], false);
                        $grade_category->aggregation = GRADE_AGGREGATE_WEIGHTED_MEAN2;
                        $grade_category->aggregateonlygraded = 0;
                        $grade_category->insert('restore');
                        $grade_category->load_grade_item();
                        // force cretion of grade_item
                    }
                } else {
                    $grade_category = null;
                }
                /// now, restore grade_items
                $items = array();
                if (!empty($info['GRADE_CATEGORY']['#']['GRADE_ITEMS']['0']['#']['GRADE_ITEM'])) {
                    //Iterate over items
                    foreach ($info['GRADE_CATEGORY']['#']['GRADE_ITEMS']['0']['#']['GRADE_ITEM'] as $ite_info) {
                        $modname = backup_todb($ite_info['#']['MODULE_NAME']['0']['#'], false);
                        $olditeminstance = backup_todb($ite_info['#']['CMINSTANCE']['0']['#'], false);
                        if (!($mod = backup_getid($restore->backup_unique_code, $modname, $olditeminstance))) {
                            continue;
                            // not restored
                        }
                        $iteminstance = $mod->new_id;
                        if (!($cm = get_coursemodule_from_instance($modname, $iteminstance, $restore->course_id))) {
                            continue;
                            // does not exist
                        }
                        if (!($grade_item = grade_item::fetch(array('itemtype' => 'mod', 'itemmodule' => $cm->modname, 'iteminstance' => $cm->instance, 'courseid' => $cm->course, 'itemnumber' => 0)))) {
                            continue;
                            // no item yet??
                        }
                        if ($grade_category) {
                            $grade_item->sortorder = backup_todb($ite_info['#']['SORT_ORDER']['0']['#'], false);
                            $grade_item->set_parent($grade_category->id);
                        }
                        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 process grade excludes
                        if (empty($ite_info['#']['GRADE_EXCEPTIONS'])) {
                            continue;
                        }
                        foreach ($ite_info['#']['GRADE_EXCEPTIONS']['0']['#']['GRADE_EXCEPTION'] as $exc_info) {
                            if ($u = backup_getid($restore->backup_unique_code, "user", backup_todb($exc_info['#']['USERID']['0']['#']))) {
                                $userid = $u->new_id;
                                $grade_grade = new grade_grade(array('itemid' => $grade_item->id, 'userid' => $userid));
                                $grade_grade->excluded = 1;
                                if ($grade_grade->id) {
                                    $grade_grade->update('restore');
                                } else {
                                    $grade_grade->insert('restore');
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    if (!defined('RESTORE_SILENTLY')) {
        //End ul
        echo '</ul>';
    }
    return $status;
}
Exemple #16
0
 public function sub_test_grade_item_compute()
 {
     $grade_item = grade_item::fetch(array('id' => $this->grade_items[1]->id));
     $this->assertTrue(method_exists($grade_item, 'compute'));
     // Check the grade_grades in the array match those in the DB then delete $this->grade_items[1]'s grade_grades.
     $this->grade_grades[3] = grade_grade::fetch(array('id' => $this->grade_grades[3]->id));
     $grade_grade = grade_grade::fetch(array('id' => $this->grade_grades[3]->id));
     $grade_grade->delete();
     $this->grade_grades[4] = grade_grade::fetch(array('id' => $this->grade_grades[4]->id));
     $grade_grade = grade_grade::fetch(array('id' => $this->grade_grades[4]->id));
     $grade_grade->delete();
     $this->grade_grades[5] = grade_grade::fetch(array('id' => $this->grade_grades[5]->id));
     $grade_grade = grade_grade::fetch(array('id' => $this->grade_grades[5]->id));
     $grade_grade->delete();
     // Recalculate the grades (its a calculation so pulls values from other grade_items) and reinsert them.
     $grade_item->compute();
     $grade_grade = grade_grade::fetch(array('userid' => $this->grade_grades[3]->userid, 'itemid' => $this->grade_grades[3]->itemid));
     $this->assertEquals($this->grade_grades[3]->finalgrade, $grade_grade->finalgrade);
     $grade_grade = grade_grade::fetch(array('userid' => $this->grade_grades[4]->userid, 'itemid' => $this->grade_grades[4]->itemid));
     $this->assertEquals($this->grade_grades[4]->finalgrade, $grade_grade->finalgrade);
     $grade_grade = grade_grade::fetch(array('userid' => $this->grade_grades[5]->userid, 'itemid' => $this->grade_grades[5]->itemid));
     $this->assertEquals($this->grade_grades[5]->finalgrade, $grade_grade->finalgrade);
 }
 function definition_after_data()
 {
     global $CFG, $COURSE;
     $mform =& $this->_form;
     if ($id = $mform->getElementValue('id')) {
         $grade_item = grade_item::fetch(array('id' => $id));
         //remove the aggregation coef element if not needed
         if ($grade_item->is_course_item()) {
             if ($mform->elementExists('parentcategory')) {
                 $mform->removeElement('parentcategory');
             }
             if ($mform->elementExists('aggregationcoef')) {
                 $mform->removeElement('aggregationcoef');
             }
         } else {
             // if we wanted to change parent of existing item - we would have to verify there are no circular references in parents!!!
             if ($mform->elementExists('parentcategory')) {
                 $mform->hardFreeze('parentcategory');
             }
             if ($grade_item->is_category_item()) {
                 $category = $grade_item->get_item_category();
                 $parent_category = $category->get_parent_category();
             } else {
                 $parent_category = $grade_item->get_parent_category();
             }
             $parent_category->apply_forced_settings();
             if (!$parent_category->is_aggregationcoef_used() or $parent_category->aggregation == GRADE_AGGREGATE_SUM) {
                 if ($mform->elementExists('aggregationcoef')) {
                     $mform->removeElement('aggregationcoef');
                 }
             } else {
                 //fix label if needed
                 $agg_el =& $mform->getElement('aggregationcoef');
                 $aggcoef = '';
                 if ($parent_category->aggregation == GRADE_AGGREGATE_WEIGHTED_MEAN) {
                     $aggcoef = 'aggregationcoefweight';
                 } else {
                     if ($parent_category->aggregation == GRADE_AGGREGATE_WEIGHTED_MEAN2) {
                         $aggcoef = 'aggregationcoefextrasum';
                     } else {
                         if ($parent_category->aggregation == GRADE_AGGREGATE_EXTRACREDIT_MEAN) {
                             $aggcoef = 'aggregationcoefextra';
                         } else {
                             if ($parent_category->aggregation == GRADE_AGGREGATE_SUM) {
                                 $aggcoef = 'aggregationcoefextrasum';
                             }
                         }
                     }
                 }
                 if ($aggcoef !== '') {
                     $agg_el->setLabel(get_string($aggcoef, 'grades'));
                     $mform->setHelpButton('aggregationcoef', array($aggcoef, get_string($aggcoef, 'grades'), 'grade'));
                 }
             }
         }
     }
     // no parent header for course category
     if (!$mform->elementExists('aggregationcoef') and !$mform->elementExists('parentcategory')) {
         $mform->removeElement('headerparent');
     }
 }
 /**
  * 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;
 }
Exemple #19
0
 /**
  * Recursive function for building the table holding the grade categories and items,
  * with CSS indentation and styles.
  *
  * @param array   $element The current tree element being rendered
  * @param boolean $totals Whether or not to print category grade items (category totals)
  * @param array   $parents An array of parent categories for the current element (used for indentation and row classes)
  *
  * @return string HTML
  */
 public function build_html_tree($element, $totals, $parents, $level, &$row_count)
 {
     global $CFG, $COURSE, $PAGE, $OUTPUT;
     $object = $element['object'];
     $eid = $element['eid'];
     $object->name = $this->gtree->get_element_header($element, true, true, true, true, true);
     $object->stripped_name = $this->gtree->get_element_header($element, false, false, false);
     $is_category_item = false;
     if ($element['type'] == 'categoryitem' || $element['type'] == 'courseitem') {
         $is_category_item = true;
     }
     $rowclasses = array();
     foreach ($parents as $parent_eid) {
         $rowclasses[] = $parent_eid;
     }
     $moveaction = '';
     $actionsmenu = new action_menu();
     $actionsmenu->set_menu_trigger(get_string('edit'));
     $actionsmenu->set_owner_selector('grade-item-' . $eid);
     $actionsmenu->set_alignment(action_menu::TL, action_menu::BL);
     if (!$is_category_item && ($icon = $this->gtree->get_edit_icon($element, $this->gpr, true))) {
         $actionsmenu->add($icon);
     }
     // MDL-49281 if grade_item already has calculation, it should be editable even if global setting is off.
     $type = $element['type'];
     $iscalculated = ($type == 'item' or $type == 'courseitem' or $type == 'categoryitem') && $object->is_calculated();
     $icon = $this->gtree->get_calculation_icon($element, $this->gpr, true);
     if ($iscalculated || $this->show_calculations && $icon) {
         $actionsmenu->add($icon);
     }
     if ($element['type'] == 'item' or $element['type'] == 'category' and $element['depth'] > 1) {
         if ($this->element_deletable($element)) {
             $aurl = new moodle_url('index.php', array('id' => $COURSE->id, 'action' => 'delete', 'eid' => $eid, 'sesskey' => sesskey()));
             $icon = new action_menu_link_secondary($aurl, new pix_icon('t/delete', get_string('delete')), get_string('delete'));
             $actionsmenu->add($icon);
         }
         $aurl = new moodle_url('index.php', array('id' => $COURSE->id, 'action' => 'moveselect', 'eid' => $eid, 'sesskey' => sesskey()));
         $moveaction .= $OUTPUT->action_icon($aurl, new pix_icon('t/move', get_string('move')));
     }
     if ($icon = $this->gtree->get_hiding_icon($element, $this->gpr, true)) {
         $actionsmenu->add($icon);
     }
     if ($icon = $this->gtree->get_reset_icon($element, $this->gpr, true)) {
         $actionsmenu->add($icon);
     }
     $actions = $OUTPUT->render($actionsmenu);
     $returnrows = array();
     $root = false;
     $id = required_param('id', PARAM_INT);
     /// prepare move target if needed
     $last = '';
     /// print the list items now
     if ($this->moving == $eid) {
         // do not diplay children
         $cell = new html_table_cell();
         $cell->colspan = 12;
         $cell->attributes['class'] = $element['type'] . ' moving column-name level' . ($level + 1) . ' level' . ($level % 2 ? 'even' : 'odd');
         $cell->text = $object->name . ' (' . get_string('move') . ')';
         return array(new html_table_row(array($cell)));
     }
     if ($element['type'] == 'category') {
         $level++;
         $this->categories[$object->id] = $object->stripped_name;
         $category = grade_category::fetch(array('id' => $object->id));
         $item = $category->get_grade_item();
         // Add aggregation coef input if not a course item and if parent category has correct aggregation type
         $dimmed = $item->is_hidden() ? 'dimmed_text' : '';
         // Before we print the category's row, we must find out how many rows will appear below it (for the filler cell's rowspan)
         $aggregation_position = grade_get_setting($COURSE->id, 'aggregationposition', $CFG->grade_aggregationposition);
         $category_total_data = null;
         // Used if aggregationposition is set to "last", so we can print it last
         $html_children = array();
         $row_count = 0;
         foreach ($element['children'] as $child_el) {
             $moveto = null;
             if (empty($child_el['object']->itemtype)) {
                 $child_el['object']->itemtype = false;
             }
             if (($child_el['object']->itemtype == 'course' || $child_el['object']->itemtype == 'category') && !$totals) {
                 continue;
             }
             $child_eid = $child_el['eid'];
             $first = '';
             if ($child_el['object']->itemtype == 'course' || $child_el['object']->itemtype == 'category') {
                 $first = array('first' => 1);
                 $child_eid = $eid;
             }
             if ($this->moving && $this->moving != $child_eid) {
                 $strmove = get_string('move');
                 $strmovehere = get_string('movehere');
                 $actions = $moveaction = '';
                 // no action icons when moving
                 $aurl = new moodle_url('index.php', array('id' => $COURSE->id, 'action' => 'move', 'eid' => $this->moving, 'moveafter' => $child_eid, 'sesskey' => sesskey()));
                 if ($first) {
                     $aurl->params($first);
                 }
                 $cell = new html_table_cell();
                 $cell->colspan = 12;
                 $cell->attributes['class'] = 'movehere level' . ($level + 1) . ' level' . ($level % 2 ? 'even' : 'odd');
                 $icon = new pix_icon('movehere', $strmovehere, null, array('class' => 'movetarget'));
                 $cell->text = $OUTPUT->action_icon($aurl, $icon);
                 $moveto = new html_table_row(array($cell));
             }
             $newparents = $parents;
             $newparents[] = $eid;
             $row_count++;
             $child_row_count = 0;
             // If moving, do not print course and category totals, but still print the moveto target box
             if ($this->moving && ($child_el['object']->itemtype == 'course' || $child_el['object']->itemtype == 'category')) {
                 $html_children[] = $moveto;
             } elseif ($child_el['object']->itemtype == 'course' || $child_el['object']->itemtype == 'category') {
                 // We don't build the item yet because we first need to know the deepest level of categories (for category/name colspans)
                 $category_total_item = $this->build_html_tree($child_el, $totals, $newparents, $level, $child_row_count);
                 if (!$aggregation_position) {
                     $html_children = array_merge($html_children, $category_total_item);
                 }
             } else {
                 $html_children = array_merge($html_children, $this->build_html_tree($child_el, $totals, $newparents, $level, $child_row_count));
                 if (!empty($moveto)) {
                     $html_children[] = $moveto;
                 }
                 if ($this->moving) {
                     $row_count++;
                 }
             }
             $row_count += $child_row_count;
             // If the child is a category, increment row_count by one more (for the extra coloured row)
             if ($child_el['type'] == 'category') {
                 $row_count++;
             }
         }
         // Print category total at the end if aggregation position is "last" (1)
         if (!empty($category_total_item) && $aggregation_position) {
             $html_children = array_merge($html_children, $category_total_item);
         }
         // Determine if we are at the root
         if (isset($element['object']->grade_item) && $element['object']->grade_item->is_course_item()) {
             $root = true;
         }
         $levelclass = "level{$level} level" . ($level % 2 ? 'odd' : 'even');
         $courseclass = '';
         if ($level == 1) {
             $courseclass = 'coursecategory';
         }
         $row = new html_table_row();
         $row->id = 'grade-item-' . $eid;
         $row->attributes['class'] = $courseclass . ' category ' . $dimmed;
         $row->attributes['data-category'] = $eid;
         $row->attributes['data-itemid'] = $category->get_grade_item()->id;
         foreach ($rowclasses as $class) {
             $row->attributes['class'] .= ' ' . $class;
         }
         $headercell = new html_table_cell();
         $headercell->header = true;
         $headercell->scope = 'row';
         $headercell->attributes['title'] = $object->stripped_name;
         $headercell->attributes['class'] = 'cell column-rowspan rowspan ' . $levelclass;
         $headercell->rowspan = $row_count + 1;
         $row->cells[] = $headercell;
         foreach ($this->columns as $column) {
             if (!($this->moving && $column->hide_when_moving)) {
                 $row->cells[] = $column->get_category_cell($category, $levelclass, ['id' => $id, 'name' => $object->name, 'level' => $level, 'actions' => $actions, 'moveaction' => $moveaction, 'eid' => $eid]);
             }
         }
         $returnrows[] = $row;
         $returnrows = array_merge($returnrows, $html_children);
         // Print a coloured row to show the end of the category across the table
         $endcell = new html_table_cell();
         $endcell->colspan = 19 - $level;
         $endcell->attributes['class'] = 'emptyrow colspan ' . $levelclass;
         $returnrows[] = new html_table_row(array($endcell));
     } else {
         // Dealing with a grade item
         $item = grade_item::fetch(array('id' => $object->id));
         $element['type'] = 'item';
         $element['object'] = $item;
         $categoryitemclass = '';
         if ($item->itemtype == 'category') {
             $categoryitemclass = 'categoryitem';
         }
         if ($item->itemtype == 'course') {
             $categoryitemclass = 'courseitem';
         }
         $dimmed = $item->is_hidden() ? "dimmed_text" : "";
         $gradeitemrow = new html_table_row();
         $gradeitemrow->id = 'grade-item-' . $eid;
         $gradeitemrow->attributes['class'] = $categoryitemclass . ' item ' . $dimmed;
         $gradeitemrow->attributes['data-itemid'] = $object->id;
         foreach ($rowclasses as $class) {
             $gradeitemrow->attributes['class'] .= ' ' . $class;
         }
         foreach ($this->columns as $column) {
             if (!($this->moving && $column->hide_when_moving)) {
                 $gradeitemrow->cells[] = $column->get_item_cell($item, array('id' => $id, 'name' => $object->name, 'level' => $level, 'actions' => $actions, 'element' => $element, 'eid' => $eid, 'moveaction' => $moveaction, 'itemtype' => $object->itemtype));
             }
         }
         $returnrows[] = $gradeitemrow;
     }
     return $returnrows;
 }
 function validation($data, $files)
 {
     global $COURSE, $DB, $CFG;
     $errors = parent::validation($data, $files);
     $mform =& $this->_form;
     $errors = array();
     if ($mform->elementExists('name')) {
         $name = trim($data['name']);
         if ($name == '') {
             $errors['name'] = get_string('required');
         }
     }
     $grade_item = grade_item::fetch(array('itemtype' => 'mod', 'itemmodule' => $data['modulename'], 'iteminstance' => $data['instance'], 'itemnumber' => 0, 'courseid' => $COURSE->id));
     if ($data['coursemodule']) {
         $cm = $DB->get_record('course_modules', array('id' => $data['coursemodule']));
     } else {
         $cm = null;
     }
     if ($mform->elementExists('cmidnumber')) {
         // verify the idnumber
         if (!grade_verify_idnumber($data['cmidnumber'], $COURSE->id, $grade_item, $cm)) {
             $errors['cmidnumber'] = get_string('idnumbertaken');
         }
     }
     // Ratings: Don't let them select an aggregate type without selecting a scale.
     // If the user has selected to use ratings but has not chosen a scale or set max points then the form is
     // invalid. If ratings have been selected then the user must select either a scale or max points.
     // This matches (horrible) logic in data_preprocessing.
     if (isset($data['assessed']) && $data['assessed'] > 0 && empty($data['scale'])) {
         $errors['assessed'] = get_string('scaleselectionrequired', 'rating');
     }
     // Check that the grade pass is a valid number.
     $gradepassvalid = false;
     if (isset($data['gradepass'])) {
         if (unformat_float($data['gradepass'], true) === false) {
             $errors['gradepass'] = get_string('err_numeric', 'form');
         } else {
             $gradepassvalid = true;
         }
     }
     // Grade to pass: ensure that the grade to pass is valid for points and scales.
     // If we are working with a scale, convert into a positive number for validation.
     if ($gradepassvalid && isset($data['gradepass']) && (!empty($data['grade']) || !empty($data['scale']))) {
         $scale = !empty($data['grade']) ? $data['grade'] : $data['scale'];
         if ($scale < 0) {
             $scalevalues = $DB->get_record('scale', array('id' => -$scale));
             $grade = count(explode(',', $scalevalues->scale));
         } else {
             $grade = $scale;
         }
         if ($data['gradepass'] > $grade) {
             $errors['gradepass'] = get_string('gradepassgreaterthangrade', 'grades', $grade);
         }
     }
     // Completion: Don't let them choose automatic completion without turning
     // on some conditions. Ignore this check when completion settings are
     // locked, as the options are then disabled.
     if (array_key_exists('completion', $data) && $data['completion'] == COMPLETION_TRACKING_AUTOMATIC && !empty($data['completionunlocked'])) {
         if (empty($data['completionview']) && empty($data['completionusegrade']) && !$this->completion_rule_enabled($data)) {
             $errors['completion'] = get_string('badautocompletion', 'completion');
         }
     }
     // Availability: Check availability field does not have errors.
     if (!empty($CFG->enableavailability)) {
         \core_availability\frontend::report_validation_errors($data, $errors);
     }
     return $errors;
 }
if ($mform->is_cancelled()) {
    redirect($returnurl);
}
$calculation = calc_formula::localize($grade_item->calculation);
$calculation = grade_item::denormalize_formula($calculation, $grade_item->courseid);
$mform->set_data(array('courseid' => $grade_item->courseid, 'calculation' => $calculation, 'id' => $grade_item->id, 'itemname' => $grade_item->itemname));
$errors = array();
if ($data = $mform->get_data(false)) {
    $calculation = calc_formula::unlocalize($data->calculation);
    $grade_item->set_calculation($calculation);
    redirect($returnurl);
} elseif (!empty($section) and $section = 'idnumbers' and !empty($idnumbers)) {
    // Handle idnumbers separately (non-mform)
    //first validate and store the new idnumbers
    foreach ($idnumbers as $giid => $value) {
        if ($gi = grade_item::fetch(array('id' => $giid))) {
            if ($gi->itemtype == 'mod') {
                $cm = get_coursemodule_from_instance($gi->itemmodule, $gi->iteminstance, $gi->courseid);
            } else {
                $cm = null;
            }
            if (!grade_verify_idnumber($value, $COURSE->id, $gi, $cm)) {
                $errors[$giid] = get_string('idnumbertaken');
                continue;
            }
            if (empty($gi->idnumber) and !$gi->add_idnumber(stripslashes($idnumbers[$gi->id]))) {
                $errors[$giid] = get_string('error');
                continue;
            }
        } else {
            $errors[$giid] = 'Could not fetch the grade_item with id=' . $giid;
 /**
  * Loads the grade_item object referenced by $this->itemid and saves it as $this->grade_item for easy access
  *
  * @return grade_item The grade_item instance referenced by $this->itemid
  */
 public function load_grade_item()
 {
     if (empty($this->itemid)) {
         debugging('Missing itemid');
         $this->grade_item = null;
         return null;
     }
     if (empty($this->grade_item)) {
         $this->grade_item = grade_item::fetch(array('id' => $this->itemid));
     } else {
         if ($this->grade_item->id != $this->itemid) {
             debugging('Itemid mismatch');
             $this->grade_item = grade_item::fetch(array('id' => $this->itemid));
         }
     }
     return $this->grade_item;
 }
Exemple #23
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);
 }
Exemple #24
0
 function validation($data, $files)
 {
     global $COURSE, $DB;
     $errors = parent::validation($data, $files);
     $mform =& $this->_form;
     $errors = array();
     if ($mform->elementExists('name')) {
         $name = trim($data['name']);
         if ($name == '') {
             $errors['name'] = get_string('required');
         }
     }
     $grade_item = grade_item::fetch(array('itemtype' => 'mod', 'itemmodule' => $data['modulename'], 'iteminstance' => $data['instance'], 'itemnumber' => 0, 'courseid' => $COURSE->id));
     if ($data['coursemodule']) {
         $cm = $DB->get_record('course_modules', array('id' => $data['coursemodule']));
     } else {
         $cm = null;
     }
     if ($mform->elementExists('cmidnumber')) {
         // verify the idnumber
         if (!grade_verify_idnumber($data['cmidnumber'], $COURSE->id, $grade_item, $cm)) {
             $errors['cmidnumber'] = get_string('idnumbertaken');
         }
     }
     // Completion: Don't let them choose automatic completion without turning
     // on some conditions
     if (array_key_exists('completion', $data) && $data['completion'] == COMPLETION_TRACKING_AUTOMATIC) {
         if (empty($data['completionview']) && empty($data['completionusegrade']) && !$this->completion_rule_enabled($data)) {
             $errors['completion'] = get_string('badautocompletion', 'completion');
         }
     }
     // Conditions: Don't let them set dates which make no sense
     if (array_key_exists('availablefrom', $data) && $data['availablefrom'] && $data['availableuntil'] && $data['availablefrom'] >= $data['availableuntil']) {
         $errors['availablefrom'] = get_string('badavailabledates', 'condition');
     }
     // Conditions: Verify that the grade conditions are numbers, and make sense.
     if (array_key_exists('conditiongradegroup', $data)) {
         foreach ($data['conditiongradegroup'] as $i => $gradedata) {
             if ($gradedata['conditiongrademin'] !== '' && !is_numeric(unformat_float($gradedata['conditiongrademin']))) {
                 $errors["conditiongradegroup[{$i}]"] = get_string('gradesmustbenumeric', 'condition');
                 continue;
             }
             if ($gradedata['conditiongrademax'] !== '' && !is_numeric(unformat_float($gradedata['conditiongrademax']))) {
                 $errors["conditiongradegroup[{$i}]"] = get_string('gradesmustbenumeric', 'condition');
                 continue;
             }
             if ($gradedata['conditiongrademin'] !== '' && $gradedata['conditiongrademax'] !== '' && unformat_float($gradedata['conditiongrademax']) <= unformat_float($gradedata['conditiongrademin'])) {
                 $errors["conditiongradegroup[{$i}]"] = get_string('badgradelimits', 'condition');
                 continue;
             }
             if ($gradedata['conditiongrademin'] === '' && $gradedata['conditiongrademax'] === '' && $gradedata['conditiongradeitemid']) {
                 $errors["conditiongradegroup[{$i}]"] = get_string('gradeitembutnolimits', 'condition');
                 continue;
             }
             if (($gradedata['conditiongrademin'] !== '' || $gradedata['conditiongrademax'] !== '') && !$gradedata['conditiongradeitemid']) {
                 $errors["conditiongradegroup[{$i}]"] = get_string('gradelimitsbutnoitem', 'condition');
                 continue;
             }
         }
     }
     // Conditions: Verify that the user profile field has not been declared more than once
     if (array_key_exists('conditionfieldgroup', $data)) {
         // Array to store the existing fields
         $arrcurrentfields = array();
         // Error message displayed if any condition is declared more than once. We use lang string because
         // this way we don't actually generate the string unless there is an error.
         $stralreadydeclaredwarning = new lang_string('fielddeclaredmultipletimes', 'condition');
         foreach ($data['conditionfieldgroup'] as $i => $fielddata) {
             if ($fielddata['conditionfield'] == 0) {
                 // Don't need to bother if none is selected
                 continue;
             }
             if (in_array($fielddata['conditionfield'], $arrcurrentfields)) {
                 $errors["conditionfieldgroup[{$i}]"] = $stralreadydeclaredwarning->out();
             }
             // Add the field to the array
             $arrcurrentfields[] = $fielddata['conditionfield'];
         }
     }
     return $errors;
 }
Exemple #25
0
 /**
  * Test checking the completion state of a quiz.
  */
 public function test_quiz_get_completion_state()
 {
     global $CFG, $DB;
     $this->resetAfterTest(true);
     // Enable completion before creating modules, otherwise the completion data is not written in DB.
     $CFG->enablecompletion = true;
     // Create a course and student.
     $course = $this->getDataGenerator()->create_course(array('enablecompletion' => true));
     $passstudent = $this->getDataGenerator()->create_user();
     $failstudent = $this->getDataGenerator()->create_user();
     $studentrole = $DB->get_record('role', array('shortname' => 'student'));
     $this->assertNotEmpty($studentrole);
     // Enrol students.
     $this->assertTrue($this->getDataGenerator()->enrol_user($passstudent->id, $course->id, $studentrole->id));
     $this->assertTrue($this->getDataGenerator()->enrol_user($failstudent->id, $course->id, $studentrole->id));
     // Make a scale and an outcome.
     $scale = $this->getDataGenerator()->create_scale();
     $data = array('courseid' => $course->id, 'fullname' => 'Team work', 'shortname' => 'Team work', 'scaleid' => $scale->id);
     $outcome = $this->getDataGenerator()->create_grade_outcome($data);
     // Make a quiz with the outcome on.
     $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz');
     $data = array('course' => $course->id, 'outcome_' . $outcome->id => 1, 'grade' => 100.0, 'questionsperpage' => 0, 'sumgrades' => 1, 'completion' => COMPLETION_TRACKING_AUTOMATIC, 'completionpass' => 1);
     $quiz = $quizgenerator->create_instance($data);
     $cm = get_coursemodule_from_id('quiz', $quiz->cmid);
     // Create a couple of questions.
     $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
     $cat = $questiongenerator->create_question_category();
     $question = $questiongenerator->create_question('numerical', null, array('category' => $cat->id));
     quiz_add_quiz_question($question->id, $quiz);
     $quizobj = quiz::create($quiz->id, $passstudent->id);
     // Set grade to pass.
     $item = grade_item::fetch(array('courseid' => $course->id, 'itemtype' => 'mod', 'itemmodule' => 'quiz', 'iteminstance' => $quiz->id, 'outcomeid' => null));
     $item->gradepass = 80;
     $item->update();
     // Start the passing attempt.
     $quba = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context());
     $quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour);
     $timenow = time();
     $attempt = quiz_create_attempt($quizobj, 1, false, $timenow, false, $passstudent->id);
     quiz_start_new_attempt($quizobj, $quba, $attempt, 1, $timenow);
     quiz_attempt_save_started($quizobj, $quba, $attempt);
     // Process some responses from the student.
     $attemptobj = quiz_attempt::create($attempt->id);
     $tosubmit = array(1 => array('answer' => '3.14'));
     $attemptobj->process_submitted_actions($timenow, false, $tosubmit);
     // Finish the attempt.
     $attemptobj = quiz_attempt::create($attempt->id);
     $this->assertTrue($attemptobj->has_response_to_at_least_one_graded_question());
     $attemptobj->process_finish($timenow, false);
     // Start the failing attempt.
     $quba = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context());
     $quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour);
     $timenow = time();
     $attempt = quiz_create_attempt($quizobj, 1, false, $timenow, false, $failstudent->id);
     quiz_start_new_attempt($quizobj, $quba, $attempt, 1, $timenow);
     quiz_attempt_save_started($quizobj, $quba, $attempt);
     // Process some responses from the student.
     $attemptobj = quiz_attempt::create($attempt->id);
     $tosubmit = array(1 => array('answer' => '0'));
     $attemptobj->process_submitted_actions($timenow, false, $tosubmit);
     // Finish the attempt.
     $attemptobj = quiz_attempt::create($attempt->id);
     $this->assertTrue($attemptobj->has_response_to_at_least_one_graded_question());
     $attemptobj->process_finish($timenow, false);
     // Check the results.
     $this->assertTrue(quiz_get_completion_state($course, $cm, $passstudent->id, 'return'));
     $this->assertFalse(quiz_get_completion_state($course, $cm, $failstudent->id, 'return'));
 }
/**
 * Returns the grade to display for the certificate.
 *
 * @param stdClass $certificate
 * @param stdClass $course
 * @param int $userid
 * @param bool $valueonly if true return only the points, %age, or letter with no prefix
 * @return string the grade result
 */
function certificate_get_grade($certificate, $course, $userid = null, $valueonly = false)
{
    global $USER;
    if (empty($userid)) {
        $userid = $USER->id;
    }
    if ($certificate->printgrade > 0) {
        if ($certificate->printgrade == 1) {
            if ($course_item = grade_item::fetch_course_item($course->id)) {
                // Check we want to add a prefix to the grade.
                $strprefix = '';
                if (!$valueonly) {
                    $strprefix = get_string('coursegrade', 'certificate') . ': ';
                }
                $grade = new grade_grade(array('itemid' => $course_item->id, 'userid' => $userid));
                $course_item->gradetype = GRADE_TYPE_VALUE;
                $coursegrade = new stdClass();
                $coursegrade->points = grade_format_gradevalue($grade->finalgrade, $course_item, true, GRADE_DISPLAY_TYPE_REAL, $decimals = 2);
                $coursegrade->percentage = grade_format_gradevalue($grade->finalgrade, $course_item, true, GRADE_DISPLAY_TYPE_PERCENTAGE, $decimals = 2);
                $coursegrade->letter = grade_format_gradevalue($grade->finalgrade, $course_item, true, GRADE_DISPLAY_TYPE_LETTER, $decimals = 0);
                if ($certificate->gradefmt == 1) {
                    $grade = $strprefix . $coursegrade->percentage;
                } else {
                    if ($certificate->gradefmt == 2) {
                        $grade = $strprefix . $coursegrade->points;
                    } else {
                        if ($certificate->gradefmt == 3) {
                            $grade = $strprefix . $coursegrade->letter;
                        }
                    }
                }
                return $grade;
            }
        } else {
            // Print the mod grade
            if ($modinfo = certificate_get_mod_grade($course, $certificate->printgrade, $userid)) {
                // Check we want to add a prefix to the grade.
                $strprefix = '';
                if (!$valueonly) {
                    $strprefix = $modinfo->name . ' ' . get_string('grade', 'certificate') . ': ';
                }
                if ($certificate->gradefmt == 1) {
                    $grade = $strprefix . $modinfo->percentage;
                } else {
                    if ($certificate->gradefmt == 2) {
                        $grade = $strprefix . $modinfo->points;
                    } else {
                        if ($certificate->gradefmt == 3) {
                            $grade = $strprefix . $modinfo->letter;
                        }
                    }
                }
                return $grade;
            }
        }
    } else {
        if ($certificate->printgrade < 0) {
            // Must be a category id.
            if ($category_item = grade_item::fetch(array('itemtype' => 'category', 'iteminstance' => -$certificate->printgrade))) {
                $category_item->gradetype = GRADE_TYPE_VALUE;
                $grade = new grade_grade(array('itemid' => $category_item->id, 'userid' => $userid));
                $category_grade = new stdClass();
                $category_grade->points = grade_format_gradevalue($grade->finalgrade, $category_item, true, GRADE_DISPLAY_TYPE_REAL, $decimals = 2);
                $category_grade->percentage = grade_format_gradevalue($grade->finalgrade, $category_item, true, GRADE_DISPLAY_TYPE_PERCENTAGE, $decimals = 2);
                $category_grade->letter = grade_format_gradevalue($grade->finalgrade, $category_item, true, GRADE_DISPLAY_TYPE_LETTER, $decimals = 0);
                if ($certificate->gradefmt == 1) {
                    $formattedgrade = $category_grade->percentage;
                } else {
                    if ($certificate->gradefmt == 2) {
                        $formattedgrade = $category_grade->points;
                    } else {
                        if ($certificate->gradefmt == 3) {
                            $formattedgrade = $category_grade->letter;
                        }
                    }
                }
                return $formattedgrade;
            }
        }
    }
    return '';
}
Exemple #27
0
 /**
  * Get the primary grade item for this assign instance.
  *
  * @return stdClass The grade_item record
  */
 public function get_grade_item()
 {
     if ($this->gradeitem) {
         return $this->gradeitem;
     }
     $instance = $this->get_instance();
     $params = array('itemtype' => 'mod', 'itemmodule' => 'assign', 'iteminstance' => $instance->id, 'courseid' => $instance->course, 'itemnumber' => 0);
     $this->gradeitem = grade_item::fetch($params);
     if (!$this->gradeitem) {
         throw new coding_exception('Improper use of the assignment class. ' . 'Cannot load the grade item.');
     }
     return $this->gradeitem;
 }
Exemple #28
0
 function definition_after_data()
 {
     global $CFG, $COURSE;
     $mform =& $this->_form;
     if ($id = $mform->getElementValue('id')) {
         $grade_item = grade_item::fetch(array('id' => $id));
         if (!$grade_item->is_raw_used()) {
             $mform->removeElement('plusfactor');
             $mform->removeElement('multfactor');
         }
         if ($grade_item->is_outcome_item()) {
             // we have to prevent incompatible modifications of outcomes if outcomes disabled
             $mform->removeElement('grademax');
             $mform->removeElement('grademin');
             $mform->removeElement('gradetype');
             $mform->removeElement('display');
             $mform->removeElement('decimals');
             $mform->hardFreeze('scaleid');
         } else {
             if ($grade_item->is_external_item()) {
                 // following items are set up from modules and should not be overrided by user
                 $mform->hardFreeze('itemname,idnumber,gradetype,grademax,grademin,scaleid');
                 //$mform->removeElement('calculation');
             }
         }
         // if we wanted to change parent of existing item - we would have to verify there are no circular references in parents!!!
         if ($mform->elementExists('parentcategory')) {
             $mform->hardFreeze('parentcategory');
         }
         $parent_category = $grade_item->get_parent_category();
         $parent_category->apply_forced_settings();
         if (!$parent_category->is_aggregationcoef_used()) {
             if ($mform->elementExists('aggregationcoef')) {
                 $mform->removeElement('aggregationcoef');
             }
         } else {
             $coefstring = $grade_item->get_coefstring();
             if ($coefstring !== '') {
                 if ($coefstring == 'aggregationcoefextrasum') {
                     // advcheckbox is not compatible with disabledIf!
                     $element =& $mform->createElement('checkbox', 'aggregationcoef', get_string($coefstring, 'grades'));
                 } else {
                     $element =& $mform->createElement('text', 'aggregationcoef', get_string($coefstring, 'grades'));
                 }
                 if ($mform->elementExists('parentcategory')) {
                     $mform->insertElementBefore($element, 'parentcategory');
                 } else {
                     $mform->insertElementBefore($element, 'id');
                 }
                 $mform->setHelpButton('aggregationcoef', array($coefstring, get_string($coefstring, 'grades'), 'grade'), true);
             }
             $mform->disabledIf('aggregationcoef', 'parentcategory', 'eq', $parent_category->id);
         }
         if ($category = $grade_item->get_item_category()) {
             if ($category->aggregation == GRADE_AGGREGATE_SUM) {
                 if ($mform->elementExists('gradetype')) {
                     $mform->hardFreeze('gradetype');
                 }
                 if ($mform->elementExists('grademin')) {
                     $mform->hardFreeze('grademin');
                 }
                 if ($mform->elementExists('grademax')) {
                     $mform->hardFreeze('grademax');
                 }
                 if ($mform->elementExists('scaleid')) {
                     $mform->removeElement('scaleid');
                 }
             }
         }
     } else {
         // all new items are manual, children of course category
         $mform->removeElement('plusfactor');
         $mform->removeElement('multfactor');
     }
     // no parent header for course category
     if (!$mform->elementExists('aggregationcoef') and !$mform->elementExists('parentcategory')) {
         $mform->removeElement('headerparent');
     }
 }
Exemple #29
0
                // so there is not need to set weightoverride here, it is done below.
                $value = $value / 100.0;
                $grade_item->aggregationcoef2 = $value;
            } else {
                if ($aggcoef == 'aggregationcoefweight' || $aggcoef == 'aggregationcoefextraweight') {
                    $grade_item->aggregationcoef = $value;
                }
            }
            $grade_item->update();
            $recreatetree = true;
            // Grade item checkbox inputs.
        } elseif (preg_match('/^(weightoverride)_([0-9]+)$/', $key, $matches)) {
            $param = $matches[1];
            $aid = $matches[2];
            $value = clean_param($value, PARAM_BOOL);
            $grade_item = grade_item::fetch(array('id' => $aid, 'courseid' => $courseid));
            $grade_item->{$param} = $value;
            $grade_item->update();
            $recreatetree = true;
        }
    }
    $originalweights = grade_helper::fetch_all_natural_weights_for_course($courseid);
    grade_regrade_final_grades($courseid);
    $alteredweights = grade_helper::fetch_all_natural_weights_for_course($courseid);
    if (array_diff($originalweights, $alteredweights)) {
        $normalisationmessage = get_string('weightsadjusted', 'grades');
    }
}
print_grade_page_head($courseid, 'settings', 'setup', get_string('categoriesanditems', 'grades'));
// Print Table of categories and items
echo $OUTPUT->box_start('gradetreebox generalbox');
Exemple #30
0
 /**
  * Denormalizes the calculation formula to [idnumber] form
  * @static
  * @param string $formula
  * @return string denormalized string
  */
 function denormalize_formula($formula, $courseid)
 {
     if (empty($formula)) {
         return '';
     }
     // denormalize formula - convert ##giXX## to [[idnumber]]
     if (preg_match_all('/##gi(\\d+)##/', $formula, $matches)) {
         foreach ($matches[1] as $id) {
             if ($grade_item = grade_item::fetch(array('id' => $id, 'courseid' => $courseid))) {
                 if (!empty($grade_item->idnumber)) {
                     $formula = str_replace('##gi' . $grade_item->id . '##', '[[' . $grade_item->idnumber . ']]', $formula);
                 }
             }
         }
     }
     return $formula;
 }