MDL-49324 grades: Create helper function for regrading on report view
[moodle.git] / grade / edit / tree / index.php
CommitLineData
e060e33d 1<?php
e060e33d 2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
f13002d5 16
1c1f64a2 17/**
53914e44 18 * The Gradebook setup page.
1c1f64a2 19 *
a153c9f2 20 * @package core_grades
1c1f64a2 21 * @copyright 2008 Nicolas Connault
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24
78ad5f3f 25require_once '../../../config.php';
3af29899 26require_once $CFG->dirroot.'/grade/lib.php';
eedd3aa2 27require_once $CFG->dirroot.'/grade/report/lib.php'; // for preferences
dc482cfa 28require_once $CFG->dirroot.'/grade/edit/tree/lib.php';
f13002d5 29
dc482cfa 30$courseid = required_param('id', PARAM_INT);
31$action = optional_param('action', 0, PARAM_ALPHA);
32$eid = optional_param('eid', 0, PARAM_ALPHANUM);
33$category = optional_param('category', null, PARAM_INT);
34$aggregationtype = optional_param('aggregationtype', null, PARAM_INT);
5bfa0d79 35
160fe5ff 36$url = new moodle_url('/grade/edit/tree/index.php', array('id' => $courseid));
160fe5ff 37$PAGE->set_url($url);
4d5059d4 38$PAGE->set_pagelayout('admin');
1c1f64a2 39
b78bb4f7 40/// Make sure they can even access this course
aaf54d21 41if (!$course = $DB->get_record('course', array('id' => $courseid))) {
c31f631b 42 print_error('nocourseid');
b78bb4f7 43}
44
f13002d5 45require_login($course);
d4060472 46$context = context_course::instance($course->id);
7a6b7acf 47require_capability('moodle/grade:manage', $context);
48
d1ae61fe 49// todo $PAGE->requires->js_module() should be used here instead
d1ae61fe
DM
50$PAGE->requires->js('/grade/edit/tree/functions.js');
51
7a6b7acf 52/// return tracking object
78ad5f3f 53$gpr = new grade_plugin_return(array('type'=>'edit', 'plugin'=>'tree', 'courseid'=>$courseid));
7a6b7acf 54$returnurl = $gpr->get_return_url(null);
b78bb4f7 55
dc482cfa 56// Change category aggregation if requested
653a8648 57if (!is_null($category) && !is_null($aggregationtype) && confirm_sesskey()) {
dc482cfa 58 if (!$grade_category = grade_category::fetch(array('id'=>$category, 'courseid'=>$courseid))) {
cac0c3ef 59 print_error('invalidcategoryid');
dc482cfa 60 }
42e5b744 61
ace9051c 62 $data = new stdClass();
dc482cfa 63 $data->aggregation = $aggregationtype;
64 grade_category::set_properties($grade_category, $data);
65 $grade_category->update();
66}
67
7a6b7acf 68//first make sure we have proper final grades - we need it for locking changes
e61f25a4
DW
69$normalisationmessage = null;
70
71$originalweights = grade_helper::fetch_all_natural_weights_for_course($courseid);
72
e61f25a4
DW
73$alteredweights = grade_helper::fetch_all_natural_weights_for_course($courseid);
74
75if (array_diff($originalweights, $alteredweights)) {
76 $normalisationmessage = get_string('weightsadjusted', 'grades');
77}
78
f13002d5 79// get the grading tree object
d3f14e42 80// note: total must be first for moving to work correctly, if you want it last moving code must be rewritten!
938e00b6 81$gtree = new grade_tree($courseid, false, false);
210611f6 82
f13002d5 83if (empty($eid)) {
84 $element = null;
85 $object = null;
5bfa0d79 86
f13002d5 87} else {
88 if (!$element = $gtree->locate_element($eid)) {
1bb0aa0f 89 print_error('invalidelementid', '', $returnurl);
f13002d5 90 }
7a6b7acf 91 $object = $element['object'];
f13002d5 92}
b3ac6c3e 93
e0724506 94$switch = grade_get_setting($course->id, 'aggregationposition', $CFG->grade_aggregationposition);
b3ac6c3e 95
826c5f86 96$strgrades = get_string('grades');
97$strgraderreport = get_string('graderreport', 'grades');
b3ac6c3e 98
f13002d5 99$moving = false;
54a007e8 100$movingeid = false;
f13002d5 101
54a007e8 102if ($action == 'moveselect') {
103 if ($eid and confirm_sesskey()) {
104 $movingeid = $eid;
105 $moving=true;
106 }
107}
108
109$grade_edit_tree = new grade_edit_tree($gtree, $movingeid, $gpr);
dc482cfa 110
f13002d5 111switch ($action) {
f13002d5 112 case 'delete':
653a8648 113 if ($eid && confirm_sesskey()) {
dc482cfa 114 if (!$grade_edit_tree->element_deletable($element)) {
23160003 115 // no deleting of external activities - they would be recreated anyway!
796a41b5 116 // exception is activity without grading or misconfigured activities
61a5ee16 117 break;
118 }
f943f4fd 119 $confirm = optional_param('confirm', 0, PARAM_BOOL);
120
cd3a391c 121 if ($confirm) {
f943f4fd 122 $object->delete('grade/report/grader/category');
123 redirect($returnurl);
124
125 } else {
7cc378fd 126 $PAGE->set_title($strgrades . ': ' . $strgraderreport);
02114f13 127 $PAGE->set_heading($course->fullname);
7cc378fd 128 echo $OUTPUT->header();
f943f4fd 129 $strdeletecheckfull = get_string('deletecheck', '', $object->get_name());
130 $optionsyes = array('eid'=>$eid, 'confirm'=>1, 'sesskey'=>sesskey(), 'id'=>$course->id, 'action'=>'delete');
131 $optionsno = array('id'=>$course->id);
dc6896ef 132 $formcontinue = new single_button(new moodle_url('index.php', $optionsyes), get_string('yes'));
3ba60ee1 133 $formcancel = new single_button(new moodle_url('index.php', $optionsno), get_string('no'), 'get');
03fcc729 134 echo $OUTPUT->confirm($strdeletecheckfull, $formcontinue, $formcancel);
5a931394 135 echo $OUTPUT->footer();
f943f4fd 136 die;
137 }
138 }
f13002d5 139 break;
140
739196ba 141 case 'autosort':
142 //TODO: implement autosorting based on order of mods on course page, categories first, manual items last
143 break;
144
f13002d5 145 case 'move':
146 if ($eid and confirm_sesskey()) {
147 $moveafter = required_param('moveafter', PARAM_ALPHANUM);
dc482cfa 148 $first = optional_param('first', false, PARAM_BOOL); // If First is set to 1, it means the target is the first child of the category $moveafter
149
f13002d5 150 if(!$after_el = $gtree->locate_element($moveafter)) {
1bb0aa0f 151 print_error('invalidelementid', '', $returnurl);
f13002d5 152 }
dc482cfa 153
f13002d5 154 $after = $after_el['object'];
f13002d5 155 $sortorder = $after->get_sortorder();
156
dc482cfa 157 if (!$first) {
158 $parent = $after->get_parent_category();
159 $object->set_parent($parent->id);
160 } else {
161 $object->set_parent($after->id);
162 }
163
f13002d5 164 $object->move_after_sortorder($sortorder);
165
166 redirect($returnurl);
167 }
168 break;
169
f13002d5 170 default:
171 break;
b3ac6c3e 172}
b3ac6c3e 173
5e212c33
AD
174//if we go straight to the db to update an element we need to recreate the tree as
175// $grade_edit_tree has already been constructed.
176//Ideally we could do the updates through $grade_edit_tree to avoid recreating it
177$recreatetree = false;
178
cd3a391c 179if ($data = data_submitted() and confirm_sesskey()) {
dc482cfa 180 // Perform bulk actions first
cd3a391c 181 if (!empty($data->bulkmove)) {
dc482cfa 182 $elements = array();
f13002d5 183
dc482cfa 184 foreach ($data as $key => $value) {
ddb9c95f 185 if (preg_match('/select_(ig[0-9]*)/', $key, $matches)) {
dc482cfa 186 $elements[] = $matches[1];
187 }
188 }
6cc3e350 189
dc482cfa 190 $grade_edit_tree->move_elements($elements, $returnurl);
6cc3e350 191 }
192
b79bf7a2 193 // Update weights (extra credits) on categories and items.
dc482cfa 194 foreach ($data as $key => $value) {
b79bf7a2
MG
195 if (preg_match('/^weight_([0-9]+)$/', $key, $matches)) {
196 $aid = $matches[1];
126d92d3 197
cd3a391c 198 $value = unformat_float($value);
61cca0b7 199 $value = clean_param($value, PARAM_FLOAT);
126d92d3 200
32ee0f83 201 $grade_item = grade_item::fetch(array('id' => $aid, 'courseid' => $courseid));
cd3a391c 202
b6a1e366 203 // Convert weight to aggregation coef2.
b79bf7a2
MG
204 $aggcoef = $grade_item->get_coefstring();
205 if ($aggcoef == 'aggregationcoefextraweightsum') {
6c37563e
FM
206 // The field 'weight' should only be sent when the checkbox 'weighoverride' is checked,
207 // so there is not need to set weightoverride here, it is done below.
b79bf7a2 208 $value = $value / 100.0;
b79bf7a2
MG
209 $grade_item->aggregationcoef2 = $value;
210 } else if ($aggcoef == 'aggregationcoefweight' || $aggcoef == 'aggregationcoefextraweight') {
211 $grade_item->aggregationcoef = $value;
45da5361 212 }
f13002d5 213
8ad3ee9c 214 $grade_item->update();
f13002d5 215
6c37563e
FM
216 $recreatetree = true;
217
218 // Grade item checkbox inputs.
219 } elseif (preg_match('/^(weightoverride)_([0-9]+)$/', $key, $matches)) {
220 $param = $matches[1];
221 $aid = $matches[2];
222 $value = clean_param($value, PARAM_BOOL);
223
224 $grade_item = grade_item::fetch(array('id' => $aid, 'courseid' => $courseid));
225 $grade_item->$param = $value;
226
227 $grade_item->update();
228
5e212c33 229 $recreatetree = true;
f13002d5 230 }
231 }
32ee0f83 232
e61f25a4
DW
233 $originalweights = grade_helper::fetch_all_natural_weights_for_course($courseid);
234
e61f25a4
DW
235 $alteredweights = grade_helper::fetch_all_natural_weights_for_course($courseid);
236 if (array_diff($originalweights, $alteredweights)) {
237 $normalisationmessage = get_string('weightsadjusted', 'grades');
519429b2 238 }
f13002d5 239}
240
0a802c9c
AN
241if (grade_regrade_final_grades_if_required($course)) {
242 $recreatetree = true;
30be6c84
DW
243}
244
53914e44 245print_grade_page_head($courseid, 'settings', 'setup', get_string('gradebooksetup', 'grades'));
76ea4e1f 246
dc482cfa 247// Print Table of categories and items
291fa827 248echo $OUTPUT->box_start('gradetreebox generalbox');
796a41b5 249
dc482cfa 250echo '<form id="gradetreeform" method="post" action="'.$returnurl.'">';
251echo '<div>';
252echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
796a41b5 253
5e212c33
AD
254//did we update something in the db and thus invalidate $grade_edit_tree?
255if ($recreatetree) {
256 $grade_edit_tree = new grade_edit_tree($gtree, $movingeid, $gpr);
257}
519429b2
AG
258// Check to see if we have a normalisation message to send.
259if (!empty($normalisationmessage)) {
260 echo $OUTPUT->notification($normalisationmessage, 'notifymessage');
261}
5e212c33 262
16be8974 263echo html_writer::table($grade_edit_tree->table);
5c75a0a3 264
dc482cfa 265echo '<div id="gradetreesubmit">';
266if (!$moving) {
267 echo '<input class="advanced" type="submit" value="'.get_string('savechanges').'" />';
268}
269
19d1a53b 270// We don't print a bulk move menu if there are no other categories than course category
54a007e8 271if (!$moving && count($grade_edit_tree->categories) > 1) {
dc482cfa 272 echo '<br /><br />';
273 echo '<input type="hidden" name="bulkmove" value="0" id="bulkmoveinput" />';
ef93efbf 274 $attributes = array('id'=>'menumoveafter', 'class' => 'ignoredirty');
f8e371f0 275 echo html_writer::label(get_string('moveselectedto', 'grades'), 'menumoveafter');
064527d6 276 echo html_writer::select($grade_edit_tree->categories, 'moveafter', '', array(''=>'choosedots'), $attributes);
c80877aa 277 $OUTPUT->add_action_handler(new component_action('change', 'submit_bulk_move'), 'menumoveafter');
2d65597b 278 echo '<div id="noscriptgradetreeform" class="hiddenifjs">
dc482cfa 279 <input type="submit" value="'.get_string('go').'" />
5fdb159e 280 </div>';
dc482cfa 281}
282
283echo '</div>';
796a41b5 284
dc482cfa 285echo '</div></form>';
286
291fa827 287echo $OUTPUT->box_end();
dc482cfa 288
289// Print action buttons
90723839 290echo $OUTPUT->container_start('buttons mdl-align');
dc482cfa 291
292if ($moving) {
5c2ed7e2 293 echo $OUTPUT->single_button(new moodle_url('index.php', array('id'=>$course->id)), get_string('cancel'), 'get');
dc482cfa 294} else {
5c2ed7e2
PS
295 echo $OUTPUT->single_button(new moodle_url('category.php', array('courseid'=>$course->id)), get_string('addcategory', 'grades'), 'get');
296 echo $OUTPUT->single_button(new moodle_url('item.php', array('courseid'=>$course->id)), get_string('additem', 'grades'), 'get');
dc482cfa 297
298 if (!empty($CFG->enableoutcomes)) {
5c2ed7e2 299 echo $OUTPUT->single_button(new moodle_url('outcomeitem.php', array('courseid'=>$course->id)), get_string('addoutcomeitem', 'grades'), 'get');
796a41b5 300 }
301
5c2ed7e2 302 //echo $OUTPUT->(new moodle_url('index.php', array('id'=>$course->id, 'action'=>'autosort')), get_string('autosort', 'grades'), 'get');
796a41b5 303}
f13002d5 304
03fcc729 305echo $OUTPUT->container_end();
dc482cfa 306
742d9165
MN
307$PAGE->requires->yui_module('moodle-core-formchangechecker',
308 'M.core_formchangechecker.init',
309 array(array(
310 'formid' => 'gradetreeform'
311 ))
312);
313$PAGE->requires->string_for_js('changesmadereallygoaway', 'moodle');
314
5a931394 315echo $OUTPUT->footer();
dc482cfa 316die;
317
6c3ef410 318