See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401] [Versions 401 and 402] [Versions 401 and 403]
1 <?php 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/>. 16 17 /** 18 * The Gradebook setup page. 19 * 20 * @package core_grades 21 * @copyright 2008 Nicolas Connault 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 define('NO_OUTPUT_BUFFERING', true); // The progress bar may be used here. 26 27 require_once '../../../config.php'; 28 require_once $CFG->dirroot.'/grade/lib.php'; 29 require_once $CFG->dirroot.'/grade/report/lib.php'; // for preferences 30 require_once $CFG->dirroot.'/grade/edit/tree/lib.php'; 31 32 $courseid = required_param('id', PARAM_INT); 33 $action = optional_param('action', 0, PARAM_ALPHA); 34 $eid = optional_param('eid', 0, PARAM_ALPHANUM); 35 $weightsadjusted = optional_param('weightsadjusted', 0, PARAM_INT); 36 37 $url = new moodle_url('/grade/edit/tree/index.php', array('id' => $courseid)); 38 $PAGE->set_url($url); 39 $PAGE->set_pagelayout('admin'); 40 41 /// Make sure they can even access this course 42 if (!$course = $DB->get_record('course', array('id' => $courseid))) { 43 throw new \moodle_exception('invalidcourseid'); 44 } 45 46 require_login($course); 47 $context = context_course::instance($course->id); 48 require_capability('moodle/grade:manage', $context); 49 50 $PAGE->requires->js_call_amd('core_grades/edittree_index', 'enhance'); 51 52 /// return tracking object 53 $gpr = new grade_plugin_return(array('type'=>'edit', 'plugin'=>'tree', 'courseid'=>$courseid)); 54 $returnurl = $gpr->get_return_url(null); 55 56 // get the grading tree object 57 // note: total must be first for moving to work correctly, if you want it last moving code must be rewritten! 58 $gtree = new grade_tree($courseid, false, false); 59 60 if (empty($eid)) { 61 $element = null; 62 $object = null; 63 64 } else { 65 if (!$element = $gtree->locate_element($eid)) { 66 throw new \moodle_exception('invalidelementid', '', $returnurl); 67 } 68 $object = $element['object']; 69 } 70 71 $switch = grade_get_setting($course->id, 'aggregationposition', $CFG->grade_aggregationposition); 72 73 $strgrades = get_string('grades'); 74 $strgraderreport = get_string('graderreport', 'grades'); 75 76 $moving = false; 77 $movingeid = false; 78 79 if ($action == 'moveselect') { 80 if ($eid and confirm_sesskey()) { 81 $movingeid = $eid; 82 $moving=true; 83 } 84 } 85 86 $grade_edit_tree = new grade_edit_tree($gtree, $movingeid, $gpr); 87 88 switch ($action) { 89 case 'duplicate': 90 if ($eid and confirm_sesskey()) { 91 if (!$el = $gtree->locate_element($eid)) { 92 throw new \moodle_exception('invalidelementid', '', $returnurl); 93 } 94 95 $object->duplicate(); 96 redirect($returnurl); 97 } 98 break; 99 100 case 'delete': 101 if ($eid && confirm_sesskey()) { 102 if (!$grade_edit_tree->element_deletable($element)) { 103 // no deleting of external activities - they would be recreated anyway! 104 // exception is activity without grading or misconfigured activities 105 break; 106 } 107 $confirm = optional_param('confirm', 0, PARAM_BOOL); 108 109 if ($confirm) { 110 $object->delete('grade/report/grader/category'); 111 redirect($returnurl); 112 113 } else { 114 $PAGE->set_title($strgrades . ': ' . $strgraderreport); 115 $PAGE->set_heading($course->fullname); 116 echo $OUTPUT->header(); 117 $strdeletecheckfull = get_string('deletecheck', '', $object->get_name()); 118 $optionsyes = array('eid'=>$eid, 'confirm'=>1, 'sesskey'=>sesskey(), 'id'=>$course->id, 'action'=>'delete'); 119 $optionsno = array('id'=>$course->id); 120 $formcontinue = new single_button(new moodle_url('index.php', $optionsyes), get_string('yes')); 121 $formcancel = new single_button(new moodle_url('index.php', $optionsno), get_string('no'), 'get'); 122 echo $OUTPUT->confirm($strdeletecheckfull, $formcontinue, $formcancel); 123 echo $OUTPUT->footer(); 124 die; 125 } 126 } 127 break; 128 129 case 'autosort': 130 //TODO: implement autosorting based on order of mods on course page, categories first, manual items last 131 break; 132 133 case 'move': 134 if ($eid and confirm_sesskey()) { 135 $moveafter = required_param('moveafter', PARAM_ALPHANUM); 136 $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 137 138 if(!$after_el = $gtree->locate_element($moveafter)) { 139 throw new \moodle_exception('invalidelementid', '', $returnurl); 140 } 141 142 $after = $after_el['object']; 143 $sortorder = $after->get_sortorder(); 144 145 if (!$first) { 146 $parent = $after->get_parent_category(); 147 $object->set_parent($parent->id); 148 } else { 149 $object->set_parent($after->id); 150 } 151 152 $object->move_after_sortorder($sortorder); 153 154 redirect($returnurl); 155 } 156 break; 157 158 default: 159 break; 160 } 161 162 //if we go straight to the db to update an element we need to recreate the tree as 163 // $grade_edit_tree has already been constructed. 164 //Ideally we could do the updates through $grade_edit_tree to avoid recreating it 165 $recreatetree = false; 166 167 if ($data = data_submitted() and confirm_sesskey()) { 168 // Perform bulk actions first 169 if (!empty($data->bulkmove)) { 170 $elements = array(); 171 172 foreach ($data as $key => $value) { 173 if (preg_match('/select_(ig[0-9]*)/', $key, $matches)) { 174 $elements[] = $matches[1]; 175 } 176 } 177 178 $grade_edit_tree->move_elements($elements, $returnurl); 179 } 180 181 // Update weights (extra credits) on categories and items. 182 foreach ($data as $key => $value) { 183 if (preg_match('/^weight_([0-9]+)$/', $key, $matches)) { 184 $aid = $matches[1]; 185 186 $value = unformat_float($value); 187 $value = clean_param($value, PARAM_FLOAT); 188 189 $grade_item = grade_item::fetch(array('id' => $aid, 'courseid' => $courseid)); 190 191 // Convert weight to aggregation coef2. 192 $aggcoef = $grade_item->get_coefstring(); 193 if ($aggcoef == 'aggregationcoefextraweightsum') { 194 // The field 'weight' should only be sent when the checkbox 'weighoverride' is checked, 195 // so there is not need to set weightoverride here, it is done below. 196 $value = $value / 100.0; 197 $grade_item->aggregationcoef2 = $value; 198 } else if ($aggcoef == 'aggregationcoefweight' || $aggcoef == 'aggregationcoefextraweight') { 199 $grade_item->aggregationcoef = $value; 200 } 201 202 $grade_item->update(); 203 204 $recreatetree = true; 205 206 // Grade item checkbox inputs. 207 } elseif (preg_match('/^(weightoverride)_([0-9]+)$/', $key, $matches)) { 208 $param = $matches[1]; 209 $aid = $matches[2]; 210 $value = clean_param($value, PARAM_BOOL); 211 212 $grade_item = grade_item::fetch(array('id' => $aid, 'courseid' => $courseid)); 213 $grade_item->$param = $value; 214 215 $grade_item->update(); 216 217 $recreatetree = true; 218 } 219 } 220 } 221 222 $originalweights = grade_helper::fetch_all_natural_weights_for_course($courseid); 223 224 /** 225 * Callback function to adjust the URL if weights changed after the 226 * regrade. 227 * 228 * @param int $courseid The course ID 229 * @param array $originalweights The weights before the regrade 230 * @param int $weightsadjusted Whether weights have been adjusted 231 * @return moodle_url A URL to redirect to after regrading when a progress bar is displayed. 232 */ 233 $grade_edit_tree_index_checkweights = function() use ($courseid, $originalweights, &$weightsadjusted) { 234 global $PAGE; 235 236 $alteredweights = grade_helper::fetch_all_natural_weights_for_course($courseid); 237 if (array_diff($originalweights, $alteredweights)) { 238 $weightsadjusted = 1; 239 return new moodle_url($PAGE->url, array('weightsadjusted' => $weightsadjusted)); 240 } 241 return $PAGE->url; 242 }; 243 244 if (grade_regrade_final_grades_if_required($course, $grade_edit_tree_index_checkweights)) { 245 $recreatetree = true; 246 } 247 248 $actionbar = new \core_grades\output\gradebook_setup_action_bar($context); 249 print_grade_page_head($courseid, 'settings', 'setup', get_string('gradebooksetup', 'grades'), 250 false, false, true, null, null, null, $actionbar); 251 252 // Print Table of categories and items 253 echo $OUTPUT->box_start('gradetreebox generalbox'); 254 255 //did we update something in the db and thus invalidate $grade_edit_tree? 256 if ($recreatetree) { 257 $grade_edit_tree = new grade_edit_tree($gtree, $movingeid, $gpr); 258 } 259 260 $bulkmoveoptions = ['' => get_string('choosedots')] + $grade_edit_tree->categories; 261 $tpldata = (object) [ 262 'actionurl' => $returnurl, 263 'sesskey' => sesskey(), 264 'showsave' => !$moving, 265 'showbulkmove' => !$moving && count($grade_edit_tree->categories) > 1, 266 'bulkmoveoptions' => array_map(function($option) use ($bulkmoveoptions) { 267 return [ 268 'name' => $bulkmoveoptions[$option], 269 'value' => $option 270 ]; 271 }, array_keys($bulkmoveoptions)) 272 ]; 273 274 // Check to see if we have a normalisation message to send. 275 if ($weightsadjusted) { 276 $notification = new \core\output\notification(get_string('weightsadjusted', 'grades'), \core\output\notification::NOTIFY_INFO); 277 $tpldata->notification = $notification->export_for_template($OUTPUT); 278 } 279 280 $tpldata->table = html_writer::table($grade_edit_tree->table); 281 282 echo $OUTPUT->render_from_template('core_grades/edit_tree', $tpldata); 283 284 echo $OUTPUT->box_end(); 285 286 // Print action buttons 287 echo $OUTPUT->container_start('buttons mdl-align'); 288 289 if ($moving) { 290 echo $OUTPUT->single_button(new moodle_url('index.php', array('id'=>$course->id)), get_string('cancel'), 'get'); 291 } 292 293 echo $OUTPUT->container_end(); 294 295 $PAGE->requires->js_call_amd('core_form/changechecker', 'watchFormById', ['gradetreeform']); 296 297 echo $OUTPUT->footer(); 298 die; 299 300
title
Description
Body
title
Description
Body
title
Description
Body
title
Body