mirror of
https://github.com/moodle/moodle.git
synced 2025-01-19 06:18:28 +01:00
Merge branch 'MDL-48618-master' of git://github.com/FMCorz/moodle
This commit is contained in:
commit
e87acc8386
@ -76,6 +76,8 @@ if (has_capability('moodle/grade:manage', $systemcontext)
|
||||
|
||||
$temp->add(new admin_setting_special_gradepointdefault());
|
||||
|
||||
$temp->add(new admin_setting_special_grademinmaxtouse());
|
||||
|
||||
$temp->add(new admin_setting_my_grades_report());
|
||||
|
||||
$temp->add(new admin_setting_configtext('gradereport_mygradeurl', new lang_string('externalurl', 'grades'),
|
||||
|
@ -65,6 +65,22 @@ class course_settings_form extends moodleform {
|
||||
$mform->addElement('select', 'aggregationposition', get_string('aggregationposition', 'grades'), $options);
|
||||
$mform->addHelpButton('aggregationposition', 'aggregationposition', 'grades');
|
||||
|
||||
if ($CFG->grade_minmaxtouse == GRADE_MIN_MAX_FROM_GRADE_ITEM) {
|
||||
$default = get_string('gradeitemminmax', 'grades');
|
||||
} else if ($CFG->grade_minmaxtouse == GRADE_MIN_MAX_FROM_GRADE_GRADE) {
|
||||
$default = get_string('gradegrademinmax', 'grades');
|
||||
} else {
|
||||
throw new coding_exception('Invalid $CFG->grade_minmaxtouse value.');
|
||||
}
|
||||
|
||||
$options = array(
|
||||
-1 => get_string('defaultprev', 'grades', $default),
|
||||
GRADE_MIN_MAX_FROM_GRADE_ITEM => get_string('gradeitemminmax', 'grades'),
|
||||
GRADE_MIN_MAX_FROM_GRADE_GRADE => get_string('gradegrademinmax', 'grades')
|
||||
);
|
||||
$mform->addElement('select', 'minmaxtouse', get_string('minmaxtouse', 'grades'), $options);
|
||||
$mform->addHelpButton('minmaxtouse', 'minmaxtouse', 'grades');
|
||||
|
||||
// Grade item settings
|
||||
$mform->addElement('header', 'grade_item_settings', get_string('gradeitemsettings', 'grades'));
|
||||
$mform->setExpanded('grade_item_settings');
|
||||
|
@ -58,7 +58,7 @@ if ($mform->is_cancelled()) {
|
||||
|
||||
} else if ($data = $mform->get_data()) {
|
||||
$data = (array)$data;
|
||||
$general = array('displaytype', 'decimalpoints', 'aggregationposition');
|
||||
$general = array('displaytype', 'decimalpoints', 'aggregationposition', 'minmaxtouse');
|
||||
foreach ($data as $key=>$value) {
|
||||
if (!in_array($key, $general) and strpos($key, 'report_') !== 0
|
||||
and strpos($key, 'import_') !== 0
|
||||
@ -69,6 +69,12 @@ if ($mform->is_cancelled()) {
|
||||
$value = null;
|
||||
}
|
||||
grade_set_setting($course->id, $key, $value);
|
||||
|
||||
$previousvalue = isset($settings->{$key}) ? $settings->{$key} : null;
|
||||
if ($key == 'minmaxtouse' && $previousvalue != $value) {
|
||||
// The min max has changed, we need to regrade the grades.
|
||||
grade_force_full_regrading($courseid);
|
||||
}
|
||||
}
|
||||
|
||||
redirect($returnurl);
|
||||
@ -76,6 +82,10 @@ if ($mform->is_cancelled()) {
|
||||
|
||||
print_grade_page_head($courseid, 'settings', 'coursesettings', get_string('coursegradesettings', 'grades'));
|
||||
|
||||
// The settings could have been changed due to a notice shown in print_grade_page_head, we need to refresh them.
|
||||
$settings = grade_get_settings($course->id);
|
||||
$mform->set_data($settings);
|
||||
|
||||
echo $OUTPUT->box_start('generalbox boxaligncenter boxwidthnormal centerpara');
|
||||
echo get_string('coursesettingsexplanation', 'grades');
|
||||
echo $OUTPUT->box_end();
|
||||
|
124
grade/lib.php
124
grade/lib.php
@ -467,6 +467,45 @@ function hide_natural_aggregation_upgrade_notice($courseid) {
|
||||
unset_config('show_sumofgrades_upgrade_' . $courseid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide warning about changed grades during upgrade from 2.8.0-2.8.6 and 2.9.0.
|
||||
*
|
||||
* @param int $courseid The current course id.
|
||||
*/
|
||||
function grade_hide_min_max_grade_upgrade_notice($courseid) {
|
||||
unset_config('show_min_max_grades_changed_' . $courseid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the grade min and max from the grade_grade.
|
||||
*
|
||||
* This is reserved for core use after an upgrade.
|
||||
*
|
||||
* @param int $courseid The current course id.
|
||||
*/
|
||||
function grade_upgrade_use_min_max_from_grade_grade($courseid) {
|
||||
grade_set_setting($courseid, 'minmaxtouse', GRADE_MIN_MAX_FROM_GRADE_GRADE);
|
||||
|
||||
grade_force_full_regrading($courseid);
|
||||
// Do this now, because it probably happened to late in the page load to be happen automatically.
|
||||
grade_regrade_final_grades($courseid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the grade min and max from the grade_item.
|
||||
*
|
||||
* This is reserved for core use after an upgrade.
|
||||
*
|
||||
* @param int $courseid The current course id.
|
||||
*/
|
||||
function grade_upgrade_use_min_max_from_grade_item($courseid) {
|
||||
grade_set_setting($courseid, 'minmaxtouse', GRADE_MIN_MAX_FROM_GRADE_ITEM);
|
||||
|
||||
grade_force_full_regrading($courseid);
|
||||
// Do this now, because it probably happened to late in the page load to be happen automatically.
|
||||
grade_regrade_final_grades($courseid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide warning about changed grades during upgrade to 2.8.
|
||||
*
|
||||
@ -487,20 +526,26 @@ function hide_aggregatesubcats_upgrade_notice($courseid) {
|
||||
* @return nothing or string if $return true
|
||||
*/
|
||||
function print_natural_aggregation_upgrade_notice($courseid, $context, $thispage, $return=false) {
|
||||
global $OUTPUT;
|
||||
global $CFG, $OUTPUT;
|
||||
$html = '';
|
||||
|
||||
// Do not do anything if they cannot manage the grades of this course.
|
||||
if (!has_capability('moodle/grade:manage', $context)) {
|
||||
return $html;
|
||||
}
|
||||
|
||||
$hidesubcatswarning = optional_param('seenaggregatesubcatsupgradedgrades', false, PARAM_BOOL) && confirm_sesskey();
|
||||
$showsubcatswarning = get_config('core', 'show_aggregatesubcats_upgrade_' . $courseid);
|
||||
$hidenaturalwarning = optional_param('seensumofgradesupgradedgrades', false, PARAM_BOOL) && confirm_sesskey();
|
||||
$shownaturalwarning = get_config('core', 'show_sumofgrades_upgrade_' . $courseid);
|
||||
|
||||
// Do not do anything if they are not a teacher.
|
||||
if ($hidesubcatswarning || $showsubcatswarning || $hidenaturalwarning || $shownaturalwarning) {
|
||||
if (!has_capability('moodle/grade:manage', $context)) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
$hideminmaxwarning = optional_param('seenminmaxupgradedgrades', false, PARAM_BOOL) && confirm_sesskey();
|
||||
$showminmaxwarning = get_config('core', 'show_min_max_grades_changed_' . $courseid);
|
||||
|
||||
$useminmaxfromgradeitem = optional_param('useminmaxfromgradeitem', false, PARAM_BOOL) && confirm_sesskey();
|
||||
$useminmaxfromgradegrade = optional_param('useminmaxfromgradegrade', false, PARAM_BOOL) && confirm_sesskey();
|
||||
|
||||
$minmaxtouse = grade_get_setting($courseid, 'minmaxtouse', $CFG->grade_minmaxtouse);
|
||||
|
||||
// Hide the warning if the user told it to go away.
|
||||
if ($hidenaturalwarning) {
|
||||
@ -511,6 +556,26 @@ function print_natural_aggregation_upgrade_notice($courseid, $context, $thispage
|
||||
hide_aggregatesubcats_upgrade_notice($courseid);
|
||||
}
|
||||
|
||||
// Hide the min/max warning if the user told it to go away.
|
||||
if ($hideminmaxwarning) {
|
||||
grade_hide_min_max_grade_upgrade_notice($courseid);
|
||||
$showminmaxwarning = false;
|
||||
}
|
||||
|
||||
if ($useminmaxfromgradegrade) {
|
||||
// Revert to the new behaviour, we now use the grade_grade for min/max.
|
||||
grade_upgrade_use_min_max_from_grade_grade($courseid);
|
||||
grade_hide_min_max_grade_upgrade_notice($courseid);
|
||||
$showminmaxwarning = false;
|
||||
|
||||
} else if ($useminmaxfromgradeitem) {
|
||||
// Apply the new logic, we now use the grade_item for min/max.
|
||||
grade_upgrade_use_min_max_from_grade_item($courseid);
|
||||
grade_hide_min_max_grade_upgrade_notice($courseid);
|
||||
$showminmaxwarning = false;
|
||||
}
|
||||
|
||||
|
||||
if (!$hidenaturalwarning && $shownaturalwarning) {
|
||||
$message = get_string('sumofgradesupgradedgrades', 'grades');
|
||||
$hidemessage = get_string('upgradedgradeshidemessage', 'grades');
|
||||
@ -535,6 +600,51 @@ function print_natural_aggregation_upgrade_notice($courseid, $context, $thispage
|
||||
$html .= $goawaybutton;
|
||||
}
|
||||
|
||||
if ($showminmaxwarning) {
|
||||
$hidemessage = get_string('upgradedgradeshidemessage', 'grades');
|
||||
$urlparams = array( 'id' => $courseid,
|
||||
'seenminmaxupgradedgrades' => true,
|
||||
'sesskey' => sesskey());
|
||||
|
||||
$goawayurl = new moodle_url($thispage, $urlparams);
|
||||
$hideminmaxbutton = $OUTPUT->single_button($goawayurl, $hidemessage, 'get');
|
||||
$moreinfo = html_writer::link(get_docs_url(get_string('minmaxtouse_link', 'grades')), get_string('moreinfo'),
|
||||
array('target' => '_blank'));
|
||||
|
||||
if ($minmaxtouse == GRADE_MIN_MAX_FROM_GRADE_ITEM) {
|
||||
// Show the message that there were min/max issues that have been resolved.
|
||||
$message = get_string('minmaxupgradedgrades', 'grades') . ' ' . $moreinfo;
|
||||
|
||||
$revertmessage = get_string('upgradedminmaxrevertmessage', 'grades');
|
||||
$urlparams = array('id' => $courseid,
|
||||
'useminmaxfromgradegrade' => true,
|
||||
'sesskey' => sesskey());
|
||||
$reverturl = new moodle_url($thispage, $urlparams);
|
||||
$revertbutton = $OUTPUT->single_button($reverturl, $revertmessage, 'get');
|
||||
|
||||
$html .= $OUTPUT->notification($message, 'notifywarning');
|
||||
$html .= $revertbutton . $hideminmaxbutton;
|
||||
|
||||
} else if ($minmaxtouse == GRADE_MIN_MAX_FROM_GRADE_GRADE) {
|
||||
// Show the warning that there are min/max issues that have not be resolved.
|
||||
$message = get_string('minmaxupgradewarning', 'grades') . ' ' . $moreinfo;
|
||||
|
||||
$fixmessage = get_string('minmaxupgradefixbutton', 'grades');
|
||||
$urlparams = array('id' => $courseid,
|
||||
'useminmaxfromgradeitem' => true,
|
||||
'sesskey' => sesskey());
|
||||
$fixurl = new moodle_url($thispage, $urlparams);
|
||||
$fixbutton = $OUTPUT->single_button($fixurl, $fixmessage, 'get');
|
||||
|
||||
$html .= $OUTPUT->notification($message, 'notifywarning');
|
||||
$html .= $fixbutton . $hideminmaxbutton;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($html)) {
|
||||
$html = html_writer::tag('div', $html, array('class' => 'core_grades_notices'));
|
||||
}
|
||||
|
||||
if ($return) {
|
||||
return $html;
|
||||
} else {
|
||||
|
@ -1086,8 +1086,8 @@ class grade_report_grader extends grade_report {
|
||||
} else {
|
||||
// The max and min for an aggregation may be different to the grade_item.
|
||||
if (!is_null($gradeval)) {
|
||||
$item->grademax = $grade->rawgrademax;
|
||||
$item->grademin = $grade->rawgrademin;
|
||||
$item->grademax = $grade->get_grade_max();
|
||||
$item->grademin = $grade->get_grade_min();
|
||||
}
|
||||
|
||||
$itemcell->text .= "<span class='gradevalue{$hidden}{$gradepass}'>" .
|
||||
|
@ -437,8 +437,8 @@ abstract class grade_report {
|
||||
$grademin = $course_item->grademin;
|
||||
$grademax = $course_item->grademax;
|
||||
if ($coursegradegrade) {
|
||||
$grademin = $coursegradegrade->rawgrademin;
|
||||
$grademax = $coursegradegrade->rawgrademax;
|
||||
$grademin = $coursegradegrade->get_grade_min();
|
||||
$grademax = $coursegradegrade->get_grade_max();
|
||||
} else {
|
||||
$coursegradegrade = new grade_grade(array('userid'=>$this->user->id, 'itemid'=>$course_item->id), false);
|
||||
}
|
||||
|
@ -238,11 +238,11 @@ class grade_report_overview extends grade_report {
|
||||
$course_item->grademin = $adjustedgrade['grademin'];
|
||||
}
|
||||
} else {
|
||||
// We must use the rawgrademin / rawgrademax because it can be different for
|
||||
// We must use the specific max/min because it can be different for
|
||||
// each grade_grade when items are excluded from sum of grades.
|
||||
if (!is_null($finalgrade)) {
|
||||
$course_item->grademin = $course_grade->rawgrademin;
|
||||
$course_item->grademax = $course_grade->rawgrademax;
|
||||
$course_item->grademin = $course_grade->get_grade_min();
|
||||
$course_item->grademax = $course_grade->get_grade_max();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -466,8 +466,8 @@ class grade_report_user extends grade_report {
|
||||
} else {
|
||||
// The max and min for an aggregation may be different to the grade_item.
|
||||
if (!is_null($gradeval)) {
|
||||
$grade_grade->grade_item->grademax = $grade_grade->rawgrademax;
|
||||
$grade_grade->grade_item->grademin = $grade_grade->rawgrademin;
|
||||
$grade_grade->grade_item->grademax = $grade_grade->get_grade_max();
|
||||
$grade_grade->grade_item->grademin = $grade_grade->get_grade_min();
|
||||
}
|
||||
}
|
||||
|
||||
|
138
grade/tests/behat/grade_minmax.feature
Normal file
138
grade/tests/behat/grade_minmax.feature
Normal file
@ -0,0 +1,138 @@
|
||||
@core @core_grades
|
||||
Feature: We can choose what min or max grade to use when aggregating grades.
|
||||
In order to what min or max grade to use
|
||||
As an teacher
|
||||
I can update modify a course setting
|
||||
|
||||
@javascript
|
||||
Scenario: Changing the min or max grade to use updates the grades accordingly
|
||||
Given the following "courses" exist:
|
||||
| fullname | shortname | category | groupmode |
|
||||
| C1 | C1 | 0 | 1 |
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email | idnumber |
|
||||
| teacher1 | Teacher | 1 | teacher1@example.com | t1 |
|
||||
| student1 | Student | 1 | student1@example.com | s1 |
|
||||
| student2 | Student | 2 | student2@example.com | s2 |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
| student1 | C1 | student |
|
||||
| student2 | C1 | student |
|
||||
And the following "grade categories" exist:
|
||||
| fullname | course |
|
||||
| CAT1 | C1 |
|
||||
And I log in as "admin"
|
||||
And I set the following administration settings values:
|
||||
| grade_minmaxtouse | Min and max grades as specified in grade item settings |
|
||||
And I am on site homepage
|
||||
And I follow "C1"
|
||||
And I navigate to "Grades" node in "Course administration"
|
||||
And I navigate to "Categories and items" node in "Grade administration > Setup"
|
||||
And I press "Add grade item"
|
||||
And I set the following fields to these values:
|
||||
| Item name | MI 1 |
|
||||
| Grade category | C1 |
|
||||
And I press "Save changes"
|
||||
And I press "Add grade item"
|
||||
And I set the following fields to these values:
|
||||
| Item name | MI 2 |
|
||||
| Grade category | C1 |
|
||||
And I press "Save changes"
|
||||
And I press "Add grade item"
|
||||
And I set the following fields to these values:
|
||||
| Item name | MI 3 |
|
||||
| Grade category | CAT1 |
|
||||
And I press "Save changes"
|
||||
And I press "Add grade item"
|
||||
And I set the following fields to these values:
|
||||
| Item name | MI 4 |
|
||||
| Grade category | CAT1 |
|
||||
And I press "Save changes"
|
||||
And I navigate to "Course grade settings" node in "Grade administration > Setup"
|
||||
And I set the field "Min and max grades used in calculation" to "Default (Min and max grades as specified in grade item settings)"
|
||||
And I set the field "Show weightings" to "Show"
|
||||
And I set the field "Show contribution to course total" to "Show"
|
||||
And I press "Save changes"
|
||||
And I navigate to "Categories and items" node in "Grade administration > Setup"
|
||||
And I set the following settings for grade item "CAT1":
|
||||
| Aggregation | Natural |
|
||||
And I log out
|
||||
And I log in as "teacher1"
|
||||
And I follow "C1"
|
||||
And I navigate to "Grades" node in "Course administration"
|
||||
And I turn editing mode on
|
||||
And I give the grade "75.00" to the user "Student 1" for the grade item "MI 1"
|
||||
And I give the grade "25.00" to the user "Student 1" for the grade item "MI 2"
|
||||
And I give the grade "50.00" to the user "Student 1" for the grade item "MI 3"
|
||||
And I give the grade "100.00" to the user "Student 1" for the grade item "MI 4"
|
||||
And I give the grade "20.00" to the user "Student 2" for the grade item "MI 1"
|
||||
And I give the grade "10.00" to the user "Student 2" for the grade item "MI 3"
|
||||
And I press "Save changes"
|
||||
And I follow "User report"
|
||||
And I select "Student 1" from the "Select all or one user" singleselect
|
||||
And the following should exist in the "user-grade" table:
|
||||
| Grade item | Calculated weight | Grade | Range | Percentage | Contribution to course total |
|
||||
| MI 1 | 25.00 % | 75.00 | 0–100 | 75.00 % | 18.75 % |
|
||||
| MI 2 | 25.00 % | 25.00 | 0–100 | 25.00 % | 6.25 % |
|
||||
| MI 3 | 50.00 % | 50.00 | 0–100 | 50.00 % | 12.50 % |
|
||||
| MI 4 | 50.00 % | 100.00 | 0–100 | 100.00 % | 25.00 % |
|
||||
| CAT1 total | 50.00 % | 150.00 | 0–200 | 75.00 % | - |
|
||||
| Course total | - | 250.00 | 0–400 | 62.50 % | - |
|
||||
And I select "Student 2" from the "Select all or one user" singleselect
|
||||
And the following should exist in the "user-grade" table:
|
||||
| Grade item | Calculated weight | Grade | Range | Percentage | Contribution to course total |
|
||||
| MI 1 | 50.00 % | 20.00 | 0–100 | 20.00 % | 10.00 % |
|
||||
| MI 2 | 0.00 % | - | 0–100 | - | 0.00 % |
|
||||
| MI 3 | 100.00 % | 10.00 | 0–100 | 10.00 % | 5.00 % |
|
||||
| MI 4 | 0.00 % | - | 0–100 | - | 0.00 % |
|
||||
| CAT1 total | 50.00 % | 10.00 | 0–100 | 10.00 % | - |
|
||||
| Course total | - | 30.00 | 0–200 | 15.00 % | - |
|
||||
And I navigate to "Categories and items" node in "Grade administration > Setup"
|
||||
And I set the following settings for grade item "MI 1":
|
||||
| Maximum grade | 50.00 |
|
||||
| Minimum grade | 5.00 |
|
||||
And I set the following settings for grade item "MI 3":
|
||||
| Maximum grade | 50.00 |
|
||||
| Minimum grade | 5.00 |
|
||||
And I follow "User report"
|
||||
And I select "Student 1" from the "Select all or one user" singleselect
|
||||
And the following should exist in the "user-grade" table:
|
||||
| Grade item | Calculated weight | Grade | Range | Percentage | Contribution to course total |
|
||||
| MI 1 | 16.67 % | 75.00 | 5–50 | 100.00 % | 25.00 % |
|
||||
| MI 2 | 33.33 % | 25.00 | 0–100 | 25.00 % | 8.33 % |
|
||||
| MI 3 | 33.33 % | 50.00 | 5–50 | 100.00 % | 16.67 % |
|
||||
| MI 4 | 66.67 % | 100.00 | 0–100 | 100.00 % | 33.33 % |
|
||||
| CAT1 total | 50.00 % | 150.00 | 0–150 | 100.00 % | - |
|
||||
| Course total | - | 250.00 | 0–300 | 83.33 % | - |
|
||||
And I select "Student 2" from the "Select all or one user" singleselect
|
||||
And the following should exist in the "user-grade" table:
|
||||
| Grade item | Calculated weight | Grade | Range | Percentage | Contribution to course total |
|
||||
| MI 1 | 50.00 % | 20.00 | 5–50 | 33.33 % | 20.00 % |
|
||||
| MI 2 | 0.00 % | - | 0–100 | - | 0.00 % |
|
||||
| MI 3 | 100.00 % | 10.00 | 5–50 | 11.11 % | 10.00 % |
|
||||
| MI 4 | 0.00 % | - | 0–100 | - | 0.00 % |
|
||||
| CAT1 total | 50.00 % | 10.00 | 0–50 | 20.00 % | - |
|
||||
| Course total | - | 30.00 | 0–100 | 30.00 % | - |
|
||||
And I navigate to "Course grade settings" node in "Grade administration > Setup"
|
||||
When I set the field "Min and max grades used in calculation" to "Initial min and max grades"
|
||||
And I press "Save changes"
|
||||
And I follow "User report"
|
||||
And I select "Student 1" from the "Select all or one user" singleselect
|
||||
Then the following should exist in the "user-grade" table:
|
||||
| Grade item | Calculated weight | Grade | Range | Percentage | Contribution to course total |
|
||||
| MI 1 | 25.00 % | 75.00 | 0–100 | 75.00 % | 18.75 % |
|
||||
| MI 2 | 25.00 % | 25.00 | 0–100 | 25.00 % | 6.25 % |
|
||||
| MI 3 | 50.00 % | 50.00 | 0–100 | 50.00 % | 12.50 % |
|
||||
| MI 4 | 50.00 % | 100.00 | 0–100 | 100.00 % | 25.00 % |
|
||||
| CAT1 total | 50.00 % | 150.00 | 0–200 | 75.00 % | - |
|
||||
| Course total | - | 250.00 | 0–400 | 62.50 % | - |
|
||||
And I select "Student 2" from the "Select all or one user" singleselect
|
||||
And the following should exist in the "user-grade" table:
|
||||
| Grade item | Calculated weight | Grade | Range | Percentage | Contribution to course total |
|
||||
| MI 1 | 50.00 % | 20.00 | 0–100 | 20.00 % | 10.00 % |
|
||||
| MI 2 | 0.00 % | - | 0–100 | - | 0.00 % |
|
||||
| MI 3 | 100.00 % | 10.00 | 0–100 | 10.00 % | 5.00 % |
|
||||
| MI 4 | 0.00 % | - | 0–100 | - | 0.00 % |
|
||||
| CAT1 total | 50.00 % | 10.00 | 0–100 | 10.00 % | - |
|
||||
| Course total | - | 30.00 | 0–200 | 15.00 % | - |
|
@ -268,6 +268,7 @@ $string['gradeexportdisplaytypes'] = 'Grade export display types';
|
||||
$string['gradeexportuserprofilefields'] = 'Grade export user profile fields';
|
||||
$string['gradeexportuserprofilefields_desc'] = 'Include these user profile fields in the grade export, separated by commas.';
|
||||
$string['gradeforstudent'] = '{$a->student}<br />{$a->item}{$a->feedback}';
|
||||
$string['gradegrademinmax'] = 'Initial min and max grades';
|
||||
$string['gradehelp'] = 'Grade help';
|
||||
$string['gradehistorylifetime'] = 'Grade history lifetime';
|
||||
$string['gradehistorylifetime_help'] = 'This specifies the length of time you want to keep history of changes in grade related tables. It is recommended to keep it as long as possible. If you experience performance problems or have limited database space, try to set lower value.';
|
||||
@ -279,6 +280,7 @@ $string['gradeitemadvanced'] = 'Advanced grade item options';
|
||||
$string['gradeitemadvanced_help'] = 'Select all elements that should be displayed as advanced when editing grade items.';
|
||||
$string['gradeitemislocked'] = 'This activity is locked in the gradebook. Changes that are made to grades in this activity will not be copied to the gradebook until it is unlocked.';
|
||||
$string['gradeitemlocked'] = 'Grading locked';
|
||||
$string['gradeitemminmax'] = 'Min and max grades as specified in grade item settings';
|
||||
$string['gradeitemmembersselected'] = 'Excluded from grading';
|
||||
$string['gradeitemnonmembers'] = 'Included in grading';
|
||||
$string['gradeitemremovemembers'] = 'Include in grading';
|
||||
@ -452,6 +454,13 @@ $string['meanselection'] = 'Grades selected for column averages';
|
||||
$string['meanselection_help'] = 'This setting determines whether cells with no grade should be included when calculating the average (mean) for each category or grade item.';
|
||||
$string['median'] = 'Median';
|
||||
$string['min'] = 'Lowest';
|
||||
$string['minmaxtouse'] = 'Min and max grades used in calculation';
|
||||
$string['minmaxtouse_desc'] = 'This setting determines whether to use the initial minimum and maximum grades from when the grade was given, or the minimum and maximum grades as specified in the settings for the grade item, when calculating the grade displayed in the gradebook. It is recommended that this setting is modified at an off-peak time, as all grades will be recalculated, which may result in a high server load.';
|
||||
$string['minmaxtouse_help'] = 'This setting determines whether to use the initial minimum and maximum grades from when the grade was given, or the minimum and maximum grades as specified in the settings for the grade item, when calculating the grade displayed in the gradebook.';
|
||||
$string['minmaxtouse_link'] = 'Grades_min_max';
|
||||
$string['minmaxupgradedgrades'] = 'Note: Some grades have been changed in order to resolve an inconsistency in the gradebook caused by a change in the minimum and maximum grades used when calculating the grade displayed. It is recommended that the changes are reviewed and accepted.';
|
||||
$string['minmaxupgradefixbutton'] = 'Resolve inconsistencies';
|
||||
$string['minmaxupgradewarning'] = 'Note: An inconsistency has been detected with some grades due to a change in the minimum and maximum grades used when calculating the grade displayed in the gradebook. It is recommended that the inconsistency is resolved by clicking the button below, though this will result in some grades being changed.';
|
||||
$string['minimum_show'] = 'Show minimum grade';
|
||||
$string['minimum_show_help'] = 'Minimum grade is used in calculating grades and weights. If not shown, minimum grade will default to zero and cannot be edited.';
|
||||
$string['missingscale'] = 'Scale must be selected';
|
||||
@ -707,7 +716,7 @@ $string['submissions'] = 'Submissions';
|
||||
$string['submittedon'] = 'Submitted: {$a}';
|
||||
$string['sumofgradesupgradedgrades'] = 'Note: The aggregation method "Sum of grades" has been changed to "Natural" as part of a site upgrade. Since "Sum of grades" was previously used in this course, it is recommended that you review this change in the gradebook.';
|
||||
$string['aggregatesubcatsupgradedgrades'] = 'Note: The aggregation setting "Aggregate including subcategories" has been removed as part of a site upgrade. Since "Aggregate including subcategories" was previously used in this course, it is recommended that you review this change in the gradebook.';
|
||||
$string['upgradedgradeshidemessage'] = 'OK';
|
||||
$string['upgradedgradeshidemessage'] = 'Dismiss notice';
|
||||
$string['switchtofullview'] = 'Switch to full view';
|
||||
$string['switchtosimpleview'] = 'Switch to simple view';
|
||||
$string['tabs'] = 'Tabs';
|
||||
@ -722,6 +731,7 @@ $string['typescale'] = 'Scale';
|
||||
$string['typescale_help'] = 'This setting determines the scale used when using the scale grade type. The scale for an activity-based grade item is set on the activity settings page.';
|
||||
$string['typetext'] = 'Text';
|
||||
$string['typevalue'] = 'Value';
|
||||
$string['upgradedminmaxrevertmessage'] = 'Revert the changes';
|
||||
$string['uncategorised'] = 'Uncategorised';
|
||||
$string['unenrolledusersinimport'] = 'This import included the following grades for users not currently enrolled in this course: {$a}';
|
||||
$string['unchangedgrade'] = 'Grade unchanged';
|
||||
|
@ -1185,6 +1185,7 @@ $string['moodleversion'] = 'Moodle version';
|
||||
$string['moodlerelease'] = 'Moodle release';
|
||||
$string['more'] = 'more';
|
||||
$string['morehelp'] = 'More help';
|
||||
$string['moreinfo'] = 'More info';
|
||||
$string['moreinformation'] = 'More information about this error';
|
||||
$string['moreprofileinfoneeded'] = 'Please tell us more about yourself';
|
||||
$string['mostrecently'] = 'most recently';
|
||||
|
@ -4921,6 +4921,51 @@ class admin_setting_special_gradelimiting extends admin_setting_configcheckbox {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Special setting for $CFG->grade_minmaxtouse.
|
||||
*
|
||||
* @package core
|
||||
* @copyright 2015 Frédéric Massart - FMCorz.net
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class admin_setting_special_grademinmaxtouse extends admin_setting_configselect {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct('grade_minmaxtouse', new lang_string('minmaxtouse', 'grades'),
|
||||
new lang_string('minmaxtouse_desc', 'grades'), GRADE_MIN_MAX_FROM_GRADE_ITEM,
|
||||
array(
|
||||
GRADE_MIN_MAX_FROM_GRADE_ITEM => get_string('gradeitemminmax', 'grades'),
|
||||
GRADE_MIN_MAX_FROM_GRADE_GRADE => get_string('gradegrademinmax', 'grades')
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the new setting.
|
||||
*
|
||||
* @param mixed $data
|
||||
* @return string empty string or error message
|
||||
*/
|
||||
function write_setting($data) {
|
||||
global $CFG;
|
||||
|
||||
$previous = $this->get_setting();
|
||||
$result = parent::write_setting($data);
|
||||
|
||||
// If saved and the value has changed.
|
||||
if (empty($result) && $previous != $data) {
|
||||
require_once($CFG->libdir . '/gradelib.php');
|
||||
grade_force_site_regrading();
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Primary grade export plugin - has state tracking.
|
||||
|
@ -4058,6 +4058,10 @@ function xmldb_main_upgrade($oldversion) {
|
||||
// Moodle v2.8.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
if ($oldversion < 2014111000.00) {
|
||||
// Coming from 2.7 or older, we need to flag the step minmaxgrade to be ignored.
|
||||
set_config('upgrade_minmaxgradestepignored', 1);
|
||||
}
|
||||
|
||||
if ($oldversion < 2014120100.00) {
|
||||
|
||||
@ -4378,5 +4382,19 @@ function xmldb_main_upgrade($oldversion) {
|
||||
// Moodle v2.9.0 release upgrade line.
|
||||
// Put any upgrade step following this.
|
||||
|
||||
if ($oldversion < 2015060400.01) {
|
||||
|
||||
// Sites that were upgrading from 2.7 and older will ignore this step.
|
||||
if (empty($CFG->upgrade_minmaxgradestepignored)) {
|
||||
|
||||
upgrade_minmaxgrade();
|
||||
|
||||
// Flags this upgrade step as already run to prevent it from running multiple times.
|
||||
set_config('upgrade_minmaxgradestepignored', 1);
|
||||
}
|
||||
|
||||
upgrade_main_savepoint(true, 2015060400.01);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -253,3 +253,13 @@ define('GRADE_NAVMETHOD_TABS', 1);
|
||||
* GRADE_NAVMETHOD_TABS - Display both a drop down and tabs to allow navigation within the gradebook
|
||||
*/
|
||||
define('GRADE_NAVMETHOD_COMBO', 2);
|
||||
|
||||
/**
|
||||
* GRADE_MIN_MAX_FROM_GRADE_ITEM - Get the grade min/max from the grade item.
|
||||
*/
|
||||
define('GRADE_MIN_MAX_FROM_GRADE_ITEM', 1);
|
||||
|
||||
/**
|
||||
* GRADE_MIN_MAX_FROM_GRADE_GRADE - Get the grade min/max from the grade grade.
|
||||
*/
|
||||
define('GRADE_MIN_MAX_FROM_GRADE_GRADE', 2);
|
||||
|
@ -465,6 +465,9 @@ class grade_category extends grade_object {
|
||||
FROM {grade_items}
|
||||
WHERE id $usql";
|
||||
$items = $DB->get_records_sql($sql, $params);
|
||||
foreach ($items as $id => $item) {
|
||||
$items[$id] = new grade_item($item);
|
||||
}
|
||||
}
|
||||
|
||||
$grade_inst = new grade_grade();
|
||||
@ -498,8 +501,12 @@ class grade_category extends grade_object {
|
||||
$grademinoverrides = array();
|
||||
|
||||
foreach ($rs as $used) {
|
||||
|
||||
if ($used->userid != $prevuser) {
|
||||
$grade = new grade_grade($used);
|
||||
if (isset($items[$grade->itemid])) {
|
||||
// Prevent grade item to be fetched from DB.
|
||||
$grade->grade_item =& $items[$grade->itemid];
|
||||
}
|
||||
if ($grade->userid != $prevuser) {
|
||||
$this->aggregate_grades($prevuser,
|
||||
$items,
|
||||
$grade_values,
|
||||
@ -507,23 +514,23 @@ class grade_category extends grade_object {
|
||||
$excluded,
|
||||
$grademinoverrides,
|
||||
$grademaxoverrides);
|
||||
$prevuser = $used->userid;
|
||||
$prevuser = $grade->userid;
|
||||
$grade_values = array();
|
||||
$excluded = array();
|
||||
$oldgrade = null;
|
||||
$grademaxoverrides = array();
|
||||
$grademinoverrides = array();
|
||||
}
|
||||
$grade_values[$used->itemid] = $used->finalgrade;
|
||||
$grademaxoverrides[$used->itemid] = $used->rawgrademax;
|
||||
$grademinoverrides[$used->itemid] = $used->rawgrademin;
|
||||
$grade_values[$grade->itemid] = $grade->finalgrade;
|
||||
$grademaxoverrides[$grade->itemid] = $grade->get_grade_max();
|
||||
$grademinoverrides[$grade->itemid] = $grade->get_grade_min();
|
||||
|
||||
if ($used->excluded) {
|
||||
$excluded[] = $used->itemid;
|
||||
if ($grade->excluded) {
|
||||
$excluded[] = $grade->itemid;
|
||||
}
|
||||
|
||||
if ($this->grade_item->id == $used->itemid) {
|
||||
$oldgrade = $used;
|
||||
if ($this->grade_item->id == $grade->itemid) {
|
||||
$oldgrade = $grade;
|
||||
}
|
||||
}
|
||||
$this->aggregate_grades($prevuser,
|
||||
|
@ -337,6 +337,51 @@ class grade_grade extends grade_object {
|
||||
$this->update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the minimum and maximum number of points this grade is graded with respect to.
|
||||
*
|
||||
* @since Moodle 2.8.7, 2.9.1
|
||||
* @return array A list containing, in order, the minimum and maximum number of points.
|
||||
*/
|
||||
protected function get_grade_min_and_max() {
|
||||
global $CFG;
|
||||
$this->load_grade_item();
|
||||
|
||||
// When the following setting is turned on we use the grade_grade raw min and max values.
|
||||
$minmaxtouse = grade_get_setting($this->grade_item->courseid, 'minmaxtouse', $CFG->grade_minmaxtouse);
|
||||
|
||||
// Only aggregate items use separate min grades.
|
||||
if ($minmaxtouse == GRADE_MIN_MAX_FROM_GRADE_GRADE || $this->grade_item->is_aggregate_item()) {
|
||||
return array($this->rawgrademin, $this->rawgrademax);
|
||||
} else {
|
||||
return array($this->grade_item->grademin, $this->grade_item->grademax);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the minimum number of points this grade is graded with.
|
||||
*
|
||||
* @since Moodle 2.8.7, 2.9.1
|
||||
* @return float The minimum number of points
|
||||
*/
|
||||
public function get_grade_min() {
|
||||
list($min, $max) = $this->get_grade_min_and_max();
|
||||
|
||||
return $min;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum number of points this grade is graded with respect to.
|
||||
*
|
||||
* @since Moodle 2.8.7, 2.9.1
|
||||
* @return float The maximum number of points
|
||||
*/
|
||||
public function get_grade_max() {
|
||||
list($min, $max) = $this->get_grade_min_and_max();
|
||||
|
||||
return $max;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns timestamp when last graded, null if no grade present
|
||||
*
|
||||
|
@ -996,6 +996,16 @@ class grade_item extends grade_object {
|
||||
return ($this->is_external_item() and !$this->is_calculated() and !$this->is_outcome_item());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the grade item is an aggreggated type grade.
|
||||
*
|
||||
* @since Moodle 2.8.7, 2.9.1
|
||||
* @return bool
|
||||
*/
|
||||
public function is_aggregate_item() {
|
||||
return ($this->is_category_item() || $this->is_course_item());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the grade item associated with the course
|
||||
*
|
||||
|
@ -230,4 +230,203 @@ class core_grade_grade_testcase extends grade_base_testcase {
|
||||
test_grade_grade_flatten_dependencies_array::test_flatten_dependencies_array($a, $b);
|
||||
$this->assertSame($expecteda, $a);
|
||||
}
|
||||
|
||||
public function test_grade_grade_min_max() {
|
||||
global $CFG;
|
||||
$initialminmaxtouse = $CFG->grade_minmaxtouse;
|
||||
|
||||
$this->setAdminUser();
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$assignrecord = $this->getDataGenerator()->create_module('assign', array('course' => $course, 'grade' => 100));
|
||||
$cm = get_coursemodule_from_instance('assign', $assignrecord->id);
|
||||
$assigncontext = context_module::instance($cm->id);
|
||||
$assign = new assign($assigncontext, $cm, $course);
|
||||
|
||||
// Fetch the assignment item.
|
||||
$giparams = array('itemtype' => 'mod', 'itemmodule' => 'assign', 'iteminstance' => $assignrecord->id,
|
||||
'courseid' => $course->id, 'itemnumber' => 0);
|
||||
$gi = grade_item::fetch($giparams);
|
||||
$this->assertEquals(0, $gi->grademin);
|
||||
$this->assertEquals(100, $gi->grademax);
|
||||
|
||||
// Give a grade to the student.
|
||||
$usergrade = $assign->get_user_grade($user->id, true);
|
||||
$usergrade->grade = 10;
|
||||
$assign->update_grade($usergrade);
|
||||
|
||||
// Check the grade stored in gradebook.
|
||||
$gg = grade_grade::fetch(array('userid' => $user->id, 'itemid' => $gi->id));
|
||||
$this->assertEquals(10, $gg->rawgrade);
|
||||
$this->assertEquals(0, $gg->get_grade_min());
|
||||
$this->assertEquals(100, $gg->get_grade_max());
|
||||
|
||||
// Change the min/max grade of the item.
|
||||
$gi->grademax = 50;
|
||||
$gi->grademin = 2;
|
||||
$gi->update();
|
||||
|
||||
// Fetch the updated item.
|
||||
$gi = grade_item::fetch($giparams);
|
||||
|
||||
// Now check the grade grade min/max with system setting.
|
||||
$CFG->grade_minmaxtouse = GRADE_MIN_MAX_FROM_GRADE_ITEM;
|
||||
grade_set_setting($course->id, 'minmaxtouse', null); // Ensure no course setting.
|
||||
|
||||
$gg = grade_grade::fetch(array('userid' => $user->id, 'itemid' => $gi->id));
|
||||
$this->assertEquals(2, $gg->get_grade_min());
|
||||
$this->assertEquals(50, $gg->get_grade_max());
|
||||
|
||||
// Now with other system setting.
|
||||
$CFG->grade_minmaxtouse = GRADE_MIN_MAX_FROM_GRADE_GRADE;
|
||||
grade_set_setting($course->id, 'minmaxtouse', null); // Ensure no course setting, and reset static cache.
|
||||
$gg = grade_grade::fetch(array('userid' => $user->id, 'itemid' => $gi->id));
|
||||
$this->assertEquals(0, $gg->get_grade_min());
|
||||
$this->assertEquals(100, $gg->get_grade_max());
|
||||
|
||||
// Now with overriden setting in course.
|
||||
$CFG->grade_minmaxtouse = GRADE_MIN_MAX_FROM_GRADE_ITEM;
|
||||
grade_set_setting($course->id, 'minmaxtouse', GRADE_MIN_MAX_FROM_GRADE_GRADE);
|
||||
$gg = grade_grade::fetch(array('userid' => $user->id, 'itemid' => $gi->id));
|
||||
$this->assertEquals(0, $gg->get_grade_min());
|
||||
$this->assertEquals(100, $gg->get_grade_max());
|
||||
|
||||
$CFG->grade_minmaxtouse = GRADE_MIN_MAX_FROM_GRADE_GRADE;
|
||||
grade_set_setting($course->id, 'minmaxtouse', GRADE_MIN_MAX_FROM_GRADE_ITEM);
|
||||
$gg = grade_grade::fetch(array('userid' => $user->id, 'itemid' => $gi->id));
|
||||
$this->assertEquals(2, $gg->get_grade_min());
|
||||
$this->assertEquals(50, $gg->get_grade_max());
|
||||
|
||||
$CFG->grade_minmaxtouse = $initialminmaxtouse;
|
||||
}
|
||||
|
||||
public function test_grade_grade_min_max_with_course_item() {
|
||||
global $CFG, $DB;
|
||||
$initialminmaxtouse = $CFG->grade_minmaxtouse;
|
||||
|
||||
$this->setAdminUser();
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$gi = grade_item::fetch_course_item($course->id);
|
||||
|
||||
// Fetch the category item.
|
||||
$this->assertEquals(0, $gi->grademin);
|
||||
$this->assertEquals(100, $gi->grademax);
|
||||
|
||||
// Give a grade to the student.
|
||||
$gi->update_final_grade($user->id, 10);
|
||||
|
||||
// Check the grade min/max stored in gradebook.
|
||||
$gg = grade_grade::fetch(array('userid' => $user->id, 'itemid' => $gi->id));
|
||||
$this->assertEquals(0, $gg->get_grade_min());
|
||||
$this->assertEquals(100, $gg->get_grade_max());
|
||||
|
||||
// Change the min/max grade of the item.
|
||||
$gi->grademin = 2;
|
||||
$gi->grademax = 50;
|
||||
$gi->update();
|
||||
|
||||
// Fetch the updated item.
|
||||
$gi = grade_item::fetch_course_item($course->id);
|
||||
|
||||
// Now check the grade grade min/max with system setting.
|
||||
$CFG->grade_minmaxtouse = GRADE_MIN_MAX_FROM_GRADE_ITEM;
|
||||
grade_set_setting($course->id, 'minmaxtouse', null); // Ensure no course setting.
|
||||
|
||||
$gg = grade_grade::fetch(array('userid' => $user->id, 'itemid' => $gi->id));
|
||||
$this->assertEquals(0, $gg->get_grade_min());
|
||||
$this->assertEquals(100, $gg->get_grade_max());
|
||||
|
||||
// Now with other system setting.
|
||||
$CFG->grade_minmaxtouse = GRADE_MIN_MAX_FROM_GRADE_GRADE;
|
||||
grade_set_setting($course->id, 'minmaxtouse', null); // Ensure no course setting, and reset static cache.
|
||||
$gg = grade_grade::fetch(array('userid' => $user->id, 'itemid' => $gi->id));
|
||||
$this->assertEquals(0, $gg->get_grade_min());
|
||||
$this->assertEquals(100, $gg->get_grade_max());
|
||||
|
||||
// Now with overriden setting in course.
|
||||
$CFG->grade_minmaxtouse = GRADE_MIN_MAX_FROM_GRADE_ITEM;
|
||||
grade_set_setting($course->id, 'minmaxtouse', GRADE_MIN_MAX_FROM_GRADE_GRADE);
|
||||
$gg = grade_grade::fetch(array('userid' => $user->id, 'itemid' => $gi->id));
|
||||
$this->assertEquals(0, $gg->get_grade_min());
|
||||
$this->assertEquals(100, $gg->get_grade_max());
|
||||
|
||||
$CFG->grade_minmaxtouse = GRADE_MIN_MAX_FROM_GRADE_GRADE;
|
||||
grade_set_setting($course->id, 'minmaxtouse', GRADE_MIN_MAX_FROM_GRADE_ITEM);
|
||||
$gg = grade_grade::fetch(array('userid' => $user->id, 'itemid' => $gi->id));
|
||||
$this->assertEquals(0, $gg->get_grade_min());
|
||||
$this->assertEquals(100, $gg->get_grade_max());
|
||||
|
||||
$CFG->grade_minmaxtouse = $initialminmaxtouse;
|
||||
}
|
||||
|
||||
public function test_grade_grade_min_max_with_category_item() {
|
||||
global $CFG, $DB;
|
||||
$initialminmaxtouse = $CFG->grade_minmaxtouse;
|
||||
|
||||
$this->setAdminUser();
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$coursegi = grade_item::fetch_course_item($course->id);
|
||||
|
||||
// Create a category item.
|
||||
$gc = new grade_category(array('courseid' => $course->id, 'fullname' => 'test'), false);
|
||||
$gc->insert();
|
||||
$gi = $gc->get_grade_item();
|
||||
$gi->grademax = 100;
|
||||
$gi->grademin = 0;
|
||||
$gi->update();
|
||||
|
||||
// Fetch the category item.
|
||||
$giparams = array('itemtype' => 'category', 'iteminstance' => $gc->id);
|
||||
$gi = grade_item::fetch($giparams);
|
||||
$this->assertEquals(0, $gi->grademin);
|
||||
$this->assertEquals(100, $gi->grademax);
|
||||
|
||||
// Give a grade to the student.
|
||||
$gi->update_final_grade($user->id, 10);
|
||||
|
||||
// Check the grade min/max stored in gradebook.
|
||||
$gg = grade_grade::fetch(array('userid' => $user->id, 'itemid' => $gi->id));
|
||||
$this->assertEquals(0, $gg->get_grade_min());
|
||||
$this->assertEquals(100, $gg->get_grade_max());
|
||||
|
||||
// Change the min/max grade of the item.
|
||||
$gi->grademin = 2;
|
||||
$gi->grademax = 50;
|
||||
$gi->update();
|
||||
|
||||
// Fetch the updated item.
|
||||
$gi = grade_item::fetch($giparams);
|
||||
|
||||
// Now check the grade grade min/max with system setting.
|
||||
$CFG->grade_minmaxtouse = GRADE_MIN_MAX_FROM_GRADE_ITEM;
|
||||
grade_set_setting($course->id, 'minmaxtouse', null); // Ensure no course setting.
|
||||
|
||||
$gg = grade_grade::fetch(array('userid' => $user->id, 'itemid' => $gi->id));
|
||||
$this->assertEquals(0, $gg->get_grade_min());
|
||||
$this->assertEquals(100, $gg->get_grade_max());
|
||||
|
||||
// Now with other system setting.
|
||||
$CFG->grade_minmaxtouse = GRADE_MIN_MAX_FROM_GRADE_GRADE;
|
||||
grade_set_setting($course->id, 'minmaxtouse', null); // Ensure no course setting, and reset static cache.
|
||||
$gg = grade_grade::fetch(array('userid' => $user->id, 'itemid' => $gi->id));
|
||||
$this->assertEquals(0, $gg->get_grade_min());
|
||||
$this->assertEquals(100, $gg->get_grade_max());
|
||||
|
||||
// Now with overriden setting in course.
|
||||
$CFG->grade_minmaxtouse = GRADE_MIN_MAX_FROM_GRADE_ITEM;
|
||||
grade_set_setting($course->id, 'minmaxtouse', GRADE_MIN_MAX_FROM_GRADE_GRADE);
|
||||
$gg = grade_grade::fetch(array('userid' => $user->id, 'itemid' => $gi->id));
|
||||
$this->assertEquals(0, $gg->get_grade_min());
|
||||
$this->assertEquals(100, $gg->get_grade_max());
|
||||
|
||||
$CFG->grade_minmaxtouse = GRADE_MIN_MAX_FROM_GRADE_GRADE;
|
||||
grade_set_setting($course->id, 'minmaxtouse', GRADE_MIN_MAX_FROM_GRADE_ITEM);
|
||||
$gg = grade_grade::fetch(array('userid' => $user->id, 'itemid' => $gi->id));
|
||||
$this->assertEquals(0, $gg->get_grade_min());
|
||||
$this->assertEquals(100, $gg->get_grade_max());
|
||||
|
||||
$CFG->grade_minmaxtouse = $initialminmaxtouse;
|
||||
}
|
||||
}
|
||||
|
@ -353,4 +353,133 @@ class core_upgradelib_testcase extends advanced_testcase {
|
||||
(object)array('userfield' => 'email', 'shortname' => null, 'operator' => 'isempty'),
|
||||
)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test upgrade minmaxgrade step.
|
||||
*/
|
||||
public function test_upgrade_minmaxgrade() {
|
||||
global $CFG, $DB;
|
||||
require_once($CFG->libdir . '/gradelib.php');
|
||||
$initialminmax = $CFG->grade_minmaxtouse;
|
||||
$this->resetAfterTest();
|
||||
|
||||
$c1 = $this->getDataGenerator()->create_course();
|
||||
$c2 = $this->getDataGenerator()->create_course();
|
||||
$c3 = $this->getDataGenerator()->create_course();
|
||||
$u1 = $this->getDataGenerator()->create_user();
|
||||
$a1 = $this->getDataGenerator()->create_module('assign', array('course' => $c1, 'grade' => 100));
|
||||
$a2 = $this->getDataGenerator()->create_module('assign', array('course' => $c2, 'grade' => 100));
|
||||
$a3 = $this->getDataGenerator()->create_module('assign', array('course' => $c3, 'grade' => 100));
|
||||
|
||||
$cm1 = get_coursemodule_from_instance('assign', $a1->id);
|
||||
$ctx1 = context_module::instance($cm1->id);
|
||||
$assign1 = new assign($ctx1, $cm1, $c1);
|
||||
|
||||
$cm2 = get_coursemodule_from_instance('assign', $a2->id);
|
||||
$ctx2 = context_module::instance($cm2->id);
|
||||
$assign2 = new assign($ctx2, $cm2, $c2);
|
||||
|
||||
$cm3 = get_coursemodule_from_instance('assign', $a3->id);
|
||||
$ctx3 = context_module::instance($cm3->id);
|
||||
$assign3 = new assign($ctx3, $cm3, $c3);
|
||||
|
||||
// Give a grade to the student.
|
||||
$ug = $assign1->get_user_grade($u1->id, true);
|
||||
$ug->grade = 10;
|
||||
$assign1->update_grade($ug);
|
||||
|
||||
$ug = $assign2->get_user_grade($u1->id, true);
|
||||
$ug->grade = 20;
|
||||
$assign2->update_grade($ug);
|
||||
|
||||
$ug = $assign3->get_user_grade($u1->id, true);
|
||||
$ug->grade = 30;
|
||||
$assign3->update_grade($ug);
|
||||
|
||||
|
||||
// Run the upgrade.
|
||||
upgrade_minmaxgrade();
|
||||
|
||||
// Nothing has happened.
|
||||
$this->assertFalse($DB->record_exists('config', array('name' => 'show_min_max_grades_changed_' . $c1->id)));
|
||||
$this->assertSame(false, grade_get_setting($c1->id, 'minmaxtouse', false, true));
|
||||
$this->assertFalse($DB->record_exists('grade_items', array('needsupdate' => 1, 'courseid' => $c1->id)));
|
||||
$this->assertFalse($DB->record_exists('config', array('name' => 'show_min_max_grades_changed_' . $c2->id)));
|
||||
$this->assertSame(false, grade_get_setting($c2->id, 'minmaxtouse', false, true));
|
||||
$this->assertFalse($DB->record_exists('grade_items', array('needsupdate' => 1, 'courseid' => $c2->id)));
|
||||
$this->assertFalse($DB->record_exists('config', array('name' => 'show_min_max_grades_changed_' . $c3->id)));
|
||||
$this->assertSame(false, grade_get_setting($c3->id, 'minmaxtouse', false, true));
|
||||
$this->assertFalse($DB->record_exists('grade_items', array('needsupdate' => 1, 'courseid' => $c3->id)));
|
||||
|
||||
// Create inconsistency in c1 and c2.
|
||||
$giparams = array('itemtype' => 'mod', 'itemmodule' => 'assign', 'iteminstance' => $a1->id,
|
||||
'courseid' => $c1->id, 'itemnumber' => 0);
|
||||
$gi = grade_item::fetch($giparams);
|
||||
$gi->grademin = 5;
|
||||
$gi->update();
|
||||
|
||||
$giparams = array('itemtype' => 'mod', 'itemmodule' => 'assign', 'iteminstance' => $a2->id,
|
||||
'courseid' => $c2->id, 'itemnumber' => 0);
|
||||
$gi = grade_item::fetch($giparams);
|
||||
$gi->grademax = 50;
|
||||
$gi->update();
|
||||
|
||||
|
||||
// C1 and C2 should be updated, but the course setting should not be set.
|
||||
$CFG->grade_minmaxtouse = GRADE_MIN_MAX_FROM_GRADE_GRADE;
|
||||
|
||||
// Run the upgrade.
|
||||
upgrade_minmaxgrade();
|
||||
|
||||
// C1 and C2 were partially updated.
|
||||
$this->assertTrue($DB->record_exists('config', array('name' => 'show_min_max_grades_changed_' . $c1->id)));
|
||||
$this->assertSame(false, grade_get_setting($c1->id, 'minmaxtouse', false, true));
|
||||
$this->assertTrue($DB->record_exists('grade_items', array('needsupdate' => 1, 'courseid' => $c1->id)));
|
||||
$this->assertTrue($DB->record_exists('config', array('name' => 'show_min_max_grades_changed_' . $c2->id)));
|
||||
$this->assertSame(false, grade_get_setting($c2->id, 'minmaxtouse', false, true));
|
||||
$this->assertTrue($DB->record_exists('grade_items', array('needsupdate' => 1, 'courseid' => $c2->id)));
|
||||
|
||||
// Nothing has happened for C3.
|
||||
$this->assertFalse($DB->record_exists('config', array('name' => 'show_min_max_grades_changed_' . $c3->id)));
|
||||
$this->assertSame(false, grade_get_setting($c3->id, 'minmaxtouse', false, true));
|
||||
$this->assertFalse($DB->record_exists('grade_items', array('needsupdate' => 1, 'courseid' => $c3->id)));
|
||||
|
||||
|
||||
// Course setting should not be set on a course that has the setting already.
|
||||
$CFG->grade_minmaxtouse = GRADE_MIN_MAX_FROM_GRADE_ITEM;
|
||||
grade_set_setting($c1->id, 'minmaxtouse', -1); // Sets different value than constant to check that it remained the same.
|
||||
|
||||
// Run the upgrade.
|
||||
upgrade_minmaxgrade();
|
||||
|
||||
// C2 was updated.
|
||||
$this->assertSame((string) GRADE_MIN_MAX_FROM_GRADE_GRADE, grade_get_setting($c2->id, 'minmaxtouse', false, true));
|
||||
|
||||
// Nothing has happened for C1.
|
||||
$this->assertSame('-1', grade_get_setting($c1->id, 'minmaxtouse', false, true));
|
||||
|
||||
// Nothing has happened for C3.
|
||||
$this->assertFalse($DB->record_exists('config', array('name' => 'show_min_max_grades_changed_' . $c3->id)));
|
||||
$this->assertSame(false, grade_get_setting($c3->id, 'minmaxtouse', false, true));
|
||||
$this->assertFalse($DB->record_exists('grade_items', array('needsupdate' => 1, 'courseid' => $c3->id)));
|
||||
|
||||
|
||||
// Final check, this time we'll unset the default config.
|
||||
unset($CFG->grade_minmaxtouse);
|
||||
grade_set_setting($c1->id, 'minmaxtouse', null);
|
||||
|
||||
// Run the upgrade.
|
||||
upgrade_minmaxgrade();
|
||||
|
||||
// C1 was updated.
|
||||
$this->assertSame((string) GRADE_MIN_MAX_FROM_GRADE_GRADE, grade_get_setting($c1->id, 'minmaxtouse', false, true));
|
||||
|
||||
// Nothing has happened for C3.
|
||||
$this->assertFalse($DB->record_exists('config', array('name' => 'show_min_max_grades_changed_' . $c3->id)));
|
||||
$this->assertSame(false, grade_get_setting($c3->id, 'minmaxtouse', false, true));
|
||||
$this->assertFalse($DB->record_exists('grade_items', array('needsupdate' => 1, 'courseid' => $c3->id)));
|
||||
|
||||
// Restore value.
|
||||
$CFG->grade_minmaxtouse = $initialminmax;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,11 @@
|
||||
This files describes API changes in core libraries and APIs,
|
||||
information provided here is intended especially for developers.
|
||||
|
||||
=== 2.9.1 ===
|
||||
|
||||
* New methods grade_grade::get_grade_max() and get_grade_min() must be used rather than directly the public properties rawgrademax and rawgrademin.
|
||||
* New method grade_item::is_aggregate_item() indicates when a grade_item is an aggreggated type grade.
|
||||
|
||||
=== 2.9 ===
|
||||
|
||||
* The default home page for users has been changed to the dashboard (formely my home). See MDL-45774.
|
||||
|
@ -2281,3 +2281,53 @@ function check_database_tables_row_format(environment_results $result) {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Upgrade the minmaxgrade setting.
|
||||
*
|
||||
* This step should only be run for sites running 2.8 or later. Sites using 2.7 will be fine
|
||||
* using the new default system setting $CFG->grade_minmaxtouse.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function upgrade_minmaxgrade() {
|
||||
global $CFG, $DB;
|
||||
|
||||
// 2 is a copy of GRADE_MIN_MAX_FROM_GRADE_GRADE.
|
||||
$settingvalue = 2;
|
||||
|
||||
// Set the course setting when:
|
||||
// - The system setting does not exist yet.
|
||||
// - The system seeting is not set to what we'd set the course setting.
|
||||
$setcoursesetting = !isset($CFG->grade_minmaxtouse) || $CFG->grade_minmaxtouse != $settingvalue;
|
||||
|
||||
// Identify the courses that have inconsistencies grade_item vs grade_grade.
|
||||
$sql = "SELECT DISTINCT(gi.courseid)
|
||||
FROM {grade_items} gi
|
||||
JOIN {grade_grades} gg
|
||||
ON gg.itemid = gi.id
|
||||
WHERE (gi.itemtype != ? AND gi.itemtype != ?)
|
||||
AND (gg.rawgrademax != gi.grademax OR gg.rawgrademin != gi.grademin)";
|
||||
|
||||
$rs = $DB->get_recordset_sql($sql, array('course', 'category'));
|
||||
foreach ($rs as $record) {
|
||||
// Flag the course to show a notice in the gradebook.
|
||||
set_config('show_min_max_grades_changed_' . $record->courseid, 1);
|
||||
|
||||
// Set the appropriate course setting so that grades displayed are not changed.
|
||||
$configname = 'minmaxtouse';
|
||||
if ($setcoursesetting &&
|
||||
!$DB->record_exists('grade_settings', array('courseid' => $record->courseid, 'name' => $configname))) {
|
||||
// Do not set the setting when the course already defines it.
|
||||
$data = new stdClass();
|
||||
$data->courseid = $record->courseid;
|
||||
$data->name = $configname;
|
||||
$data->value = $settingvalue;
|
||||
$DB->insert_record('grade_settings', $data);
|
||||
}
|
||||
|
||||
// Mark the grades to be regraded.
|
||||
$DB->set_field('grade_items', 'needsupdate', 1, array('courseid' => $record->courseid));
|
||||
}
|
||||
$rs->close();
|
||||
}
|
||||
|
@ -1,6 +1,10 @@
|
||||
/*** Grades ***/
|
||||
.allcoursegrades {width: 100%;text-align: right;padding: 4px 0px 5px 0px;}
|
||||
|
||||
.core_grades_notices .singlebutton {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.path-grade-edit .buttons {text-align:center;}
|
||||
.path-grade-edit-tree .idnumber {margin-left: 15px;}
|
||||
.path-grade-edit-tree .movetarget {position: relative;width: 80px;height: 16px;}
|
||||
|
@ -17,6 +17,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Grade upgrade notice.
|
||||
.core_grades_notices {
|
||||
.singlebutton {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
// Rubrics
|
||||
#page-grade-grading-manage {
|
||||
#activemethodselector {
|
||||
|
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user