MDL-47055 core_grade: implemented support for extra credit within natural weighting
[moodle.git] / grade / edit / tree / lib.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/>.
dc482cfa 16
a153c9f2
AD
17/**
18 * A library of classes used by the grade edit pages
19 *
20 * @package core_grades
21 * @copyright 2009 Nicolas Connault
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24
dc482cfa 25class grade_edit_tree {
26 public $columns = array();
27
28 /**
39873128 29 * @var grade_tree $gtree @see grade/lib.php
dc482cfa 30 */
31 public $gtree;
32
33 /**
34 * @var grade_plugin_return @see grade/lib.php
35 */
36 public $gpr;
37
38 /**
39 * @var string $moving The eid of the category or item being moved
40 */
41 public $moving;
42
43 public $deepest_level;
44
653a8648 45 public $uses_extra_credit = false;
46
47 public $uses_weight = false;
71297a3f 48
677bc073
JO
49 public $uses_weight2 = false;
50
54a007e8 51 public $table;
71297a3f 52
54a007e8 53 public $categories = array();
0e999796
AD
54
55 /**
56 * Show calculator icons next to manual grade items
57 * @var bool $show_calculations
58 */
59 private $show_calculations;
60
dc482cfa 61 /**
62 * Constructor
63 */
64 public function __construct($gtree, $moving=false, $gpr) {
54a007e8 65 global $USER, $OUTPUT, $COURSE;
66
0e999796
AD
67 $systemdefault = get_config('moodle', 'grade_report_showcalculations');
68 $this->show_calculations = get_user_preferences('grade_report_showcalculations', $systemdefault);
69
dc482cfa 70 $this->gtree = $gtree;
71 $this->moving = $moving;
72 $this->gpr = $gpr;
73 $this->deepest_level = $this->get_deepest_level($this->gtree->top_element);
74
75 $this->columns = array(grade_edit_tree_column::factory('name', array('deepest_level' => $this->deepest_level)),
653a8648 76 grade_edit_tree_column::factory('aggregation', array('flag' => true)));
77
677bc073
JO
78 if ($this->uses_weight2) {
79 $this->columns[] = grade_edit_tree_column::factory('weight', array('adv' => 'aggregationcoef2'));
80 }
81
653a8648 82 if ($this->uses_weight) {
83 $this->columns[] = grade_edit_tree_column::factory('weight', array('adv' => 'aggregationcoef'));
84 }
85 if ($this->uses_extra_credit) {
86 $this->columns[] = grade_edit_tree_column::factory('extracredit', array('adv' => 'aggregationcoef'));
87 }
88
89 $this->columns[] = grade_edit_tree_column::factory('range'); // This is not a setting... How do we deal with it?
90 $this->columns[] = grade_edit_tree_column::factory('aggregateonlygraded', array('flag' => true));
91 $this->columns[] = grade_edit_tree_column::factory('aggregatesubcats', array('flag' => true));
92 $this->columns[] = grade_edit_tree_column::factory('aggregateoutcomes', array('flag' => true));
93 $this->columns[] = grade_edit_tree_column::factory('droplow', array('flag' => true));
94 $this->columns[] = grade_edit_tree_column::factory('keephigh', array('flag' => true));
95 $this->columns[] = grade_edit_tree_column::factory('multfactor', array('adv' => true));
96 $this->columns[] = grade_edit_tree_column::factory('plusfactor', array('adv' => true));
97 $this->columns[] = grade_edit_tree_column::factory('actions');
98 $this->columns[] = grade_edit_tree_column::factory('select');
54a007e8 99
100 $mode = ($USER->gradeediting[$COURSE->id]) ? 'advanced' : 'simple';
71297a3f 101
54a007e8 102 $widthstyle = '';
103 if ($mode == 'simple') {
104 $widthstyle = ' style="width:auto;" ';
105 }
106
107 $this->table = new html_table();
108 $this->table->id = "grade_edit_tree_table";
109 $this->table->cellpadding = 5;
16be8974 110 $this->table->attributes['class'] = 'generaltable ' . $mode;
54a007e8 111 $this->table->style = $widthstyle;
112
113 foreach ($this->columns as $column) {
114 if (!($this->moving && $column->hide_when_moving) && !$column->is_hidden($mode)) {
115 $this->table->head[] = $column->get_header_cell();
116 }
117 }
118
119 $rowcount = 0;
120 $this->table->data = $this->build_html_tree($this->gtree->top_element, true, array(), 0, $rowcount);
dc482cfa 121 }
122
123 /**
124 * Recursive function for building the table holding the grade categories and items,
125 * with CSS indentation and styles.
126 *
1c1f64a2 127 * @param array $element The current tree element being rendered
128 * @param boolean $totals Whether or not to print category grade items (category totals)
129 * @param array $parents An array of parent categories for the current element (used for indentation and row classes)
dc482cfa 130 *
131 * @return string HTML
132 */
54a007e8 133 public function build_html_tree($element, $totals, $parents, $level, &$row_count) {
6b608f8f 134 global $CFG, $COURSE, $USER, $OUTPUT;
71297a3f 135
dc482cfa 136 $object = $element['object'];
137 $eid = $element['eid'];
138 $object->name = $this->gtree->get_element_header($element, true, true, false);
139 $object->stripped_name = $this->gtree->get_element_header($element, false, false, false);
140
141 $is_category_item = false;
142 if ($element['type'] == 'categoryitem' || $element['type'] == 'courseitem') {
143 $is_category_item = true;
144 }
145
54a007e8 146 $rowclasses = array();
dc482cfa 147 foreach ($parents as $parent_eid) {
54a007e8 148 $rowclasses[] = $parent_eid;
dc482cfa 149 }
150
151 $actions = '';
152
153 if (!$is_category_item) {
154 $actions .= $this->gtree->get_edit_icon($element, $this->gpr);
155 }
156
0e999796
AD
157 if ($this->show_calculations) {
158 $actions .= $this->gtree->get_calculation_icon($element, $this->gpr);
159 }
dc482cfa 160
161 if ($element['type'] == 'item' or ($element['type'] == 'category' and $element['depth'] > 1)) {
162 if ($this->element_deletable($element)) {
8ae8bf8a 163 $aurl = new moodle_url('index.php', array('id' => $COURSE->id, 'action' => 'delete', 'eid' => $eid, 'sesskey' => sesskey()));
c63923bd 164 $actions .= $OUTPUT->action_icon($aurl, new pix_icon('t/delete', get_string('delete')));
dc482cfa 165 }
1c1f64a2 166
8ae8bf8a 167 $aurl = new moodle_url('index.php', array('id' => $COURSE->id, 'action' => 'moveselect', 'eid' => $eid, 'sesskey' => sesskey()));
c63923bd 168 $actions .= $OUTPUT->action_icon($aurl, new pix_icon('t/move', get_string('move')));
dc482cfa 169 }
170
171 $actions .= $this->gtree->get_hiding_icon($element, $this->gpr);
172 $actions .= $this->gtree->get_locking_icon($element, $this->gpr);
173
174 $mode = ($USER->gradeediting[$COURSE->id]) ? 'advanced' : 'simple';
175
54a007e8 176 $returnrows = array();
dc482cfa 177 $root = false;
178
dc482cfa 179 $id = required_param('id', PARAM_INT);
180
181 /// prepare move target if needed
182 $last = '';
183
184 /// print the list items now
185 if ($this->moving == $eid) {
dc482cfa 186 // do not diplay children
54a007e8 187 $cell = new html_table_cell();
188 $cell->colspan = 12;
16be8974 189 $cell->attributes['class'] = $element['type'] . ' moving';
54a007e8 190 $cell->text = $object->name.' ('.get_string('move').')';
8cea545e 191 return array(new html_table_row(array($cell)));
dc482cfa 192 }
193
194 if ($element['type'] == 'category') {
195 $level++;
54a007e8 196 $this->categories[$object->id] = $object->stripped_name;
dc482cfa 197 $category = grade_category::fetch(array('id' => $object->id));
198 $item = $category->get_grade_item();
199
200 // Add aggregation coef input if not a course item and if parent category has correct aggregation type
54a007e8 201 $dimmed = ($item->is_hidden()) ? 'dimmed' : '';
dc482cfa 202
203 // Before we print the category's row, we must find out how many rows will appear below it (for the filler cell's rowspan)
204 $aggregation_position = grade_get_setting($COURSE->id, 'aggregationposition', $CFG->grade_aggregationposition);
205 $category_total_data = null; // Used if aggregationposition is set to "last", so we can print it last
206
54a007e8 207 $html_children = array();
dc482cfa 208
209 $row_count = 0;
210
211 foreach($element['children'] as $child_el) {
54a007e8 212 $moveto = null;
dc482cfa 213
214 if (empty($child_el['object']->itemtype)) {
215 $child_el['object']->itemtype = false;
216 }
217
218 if (($child_el['object']->itemtype == 'course' || $child_el['object']->itemtype == 'category') && !$totals) {
219 continue;
220 }
221
54a007e8 222 $child_eid = $child_el['eid'];
dc482cfa 223 $first = '';
224
225 if ($child_el['object']->itemtype == 'course' || $child_el['object']->itemtype == 'category') {
1c1f64a2 226 $first = array('first' => 1);
dc482cfa 227 $child_eid = $eid;
228 }
229
230 if ($this->moving && $this->moving != $child_eid) {
231
232 $strmove = get_string('move');
233 $strmovehere = get_string('movehere');
234 $actions = ''; // no action icons when moving
235
8ae8bf8a 236 $aurl = new moodle_url('index.php', array('id' => $COURSE->id, 'action' => 'move', 'eid' => $this->moving, 'moveafter' => $child_eid, 'sesskey' => sesskey()));
1c1f64a2 237 if ($first) {
8ae8bf8a 238 $aurl->params($first);
1c1f64a2 239 }
71297a3f 240
54a007e8 241 $cell = new html_table_cell();
242 $cell->colspan = 12;
6ef4878b 243
84d32de3
AD
244 $icon = new pix_icon('movehere', $strmovehere, null, array('class'=>'movetarget'));
245 $cell->text = $OUTPUT->action_icon($aurl, $icon);
1c1f64a2 246
8cea545e 247 $moveto = new html_table_row(array($cell));
dc482cfa 248 }
249
250 $newparents = $parents;
251 $newparents[] = $eid;
252
253 $row_count++;
254 $child_row_count = 0;
255
256 // If moving, do not print course and category totals, but still print the moveto target box
257 if ($this->moving && ($child_el['object']->itemtype == 'course' || $child_el['object']->itemtype == 'category')) {
54a007e8 258 $html_children[] = $moveto;
dc482cfa 259 } elseif ($child_el['object']->itemtype == 'course' || $child_el['object']->itemtype == 'category') {
260 // We don't build the item yet because we first need to know the deepest level of categories (for category/name colspans)
54a007e8 261 $category_total_item = $this->build_html_tree($child_el, $totals, $newparents, $level, $child_row_count);
dc482cfa 262 if (!$aggregation_position) {
54a007e8 263 $html_children = array_merge($html_children, $category_total_item);
dc482cfa 264 }
265 } else {
54a007e8 266 $html_children = array_merge($html_children, $this->build_html_tree($child_el, $totals, $newparents, $level, $child_row_count));
267 if (!empty($moveto)) {
268 $html_children[] = $moveto;
269 }
dc482cfa 270
271 if ($this->moving) {
272 $row_count++;
273 }
274 }
275
276 $row_count += $child_row_count;
277
278 // If the child is a category, increment row_count by one more (for the extra coloured row)
279 if ($child_el['type'] == 'category') {
280 $row_count++;
281 }
282 }
283
284 // Print category total at the end if aggregation position is "last" (1)
285 if (!empty($category_total_item) && $aggregation_position) {
54a007e8 286 $html_children = array_merge($html_children, $category_total_item);
dc482cfa 287 }
288
54a007e8 289 // Determine if we are at the root
dc482cfa 290 if (isset($element['object']->grade_item) && $element['object']->grade_item->is_course_item()) {
dc482cfa 291 $root = true;
292 }
293
54a007e8 294 $levelclass = "level$level";
2be6ca78 295
b189277f 296 $courseclass = '';
297 if ($level == 1) {
298 $courseclass = 'coursecategory';
299 }
71297a3f 300
54a007e8 301 $row = new html_table_row();
16be8974 302 $row->attributes['class'] = $courseclass . ' category ' . $dimmed;
54a007e8 303 foreach ($rowclasses as $class) {
16be8974 304 $row->attributes['class'] .= ' ' . $class;
54a007e8 305 }
dc482cfa 306
54a007e8 307 $headercell = new html_table_cell();
308 $headercell->header = true;
309 $headercell->scope = 'row';
16be8974
DM
310 $headercell->attributes['title'] = $object->stripped_name;
311 $headercell->attributes['class'] = 'cell rowspan ' . $levelclass;
bd26d932 312 $headercell->rowspan = $row_count + 1;
54a007e8 313 $row->cells[] = $headercell;
dc482cfa 314
315 foreach ($this->columns as $column) {
316 if (!($this->moving && $column->hide_when_moving) && !$column->is_hidden($mode)) {
54a007e8 317 $row->cells[] = $column->get_category_cell($category, $levelclass, array('id' => $id, 'name' => $object->name, 'level' => $level, 'actions' => $actions, 'eid' => $eid));
dc482cfa 318 }
319 }
71297a3f 320
54a007e8 321 $returnrows[] = $row;
dc482cfa 322
54a007e8 323 $returnrows = array_merge($returnrows, $html_children);
dc482cfa 324
6ef4878b 325 // Print a coloured row to show the end of the category across the table
54a007e8 326 $endcell = new html_table_cell();
327 $endcell->colspan = (19 - $level);
16be8974 328 $endcell->attributes['class'] = 'colspan ' . $levelclass;
54a007e8 329
0e35ba6f 330 $returnrows[] = new html_table_row(array($endcell));
dc482cfa 331
332 } else { // Dealing with a grade item
333
334 $item = grade_item::fetch(array('id' => $object->id));
335 $element['type'] = 'item';
336 $element['object'] = $item;
2be6ca78 337
b189277f 338 $categoryitemclass = '';
339 if ($item->itemtype == 'category') {
340 $categoryitemclass = 'categoryitem';
341 }
dc482cfa 342
54a007e8 343 $dimmed = ($item->is_hidden()) ? "dimmed_text" : "";
344 $gradeitemrow = new html_table_row();
16be8974 345 $gradeitemrow->attributes['class'] = $categoryitemclass . ' item ' . $dimmed;
54a007e8 346 foreach ($rowclasses as $class) {
16be8974 347 $gradeitemrow->attributes['class'] .= ' ' . $class;
54a007e8 348 }
dc482cfa 349
350 foreach ($this->columns as $column) {
351 if (!($this->moving && $column->hide_when_moving) && !$column->is_hidden($mode)) {
54a007e8 352 $gradeitemrow->cells[] = $column->get_item_cell($item, array('id' => $id, 'name' => $object->name, 'level' => $level, 'actions' => $actions,
dc482cfa 353 'element' => $element, 'eid' => $eid, 'itemtype' => $object->itemtype));
354 }
355 }
356
54a007e8 357 $returnrows[] = $gradeitemrow;
dc482cfa 358 }
359
54a007e8 360 return $returnrows;
dc482cfa 361
362 }
363
364 /**
365 * Given a grade_item object, returns a labelled input if an aggregation coefficient (weight or extra credit) applies to it.
366 * @param grade_item $item
653a8648 367 * @param string type "extra" or "weight": the type of the column hosting the weight input
dc482cfa 368 * @return string HTML
369 */
e2bb3c92 370 static function get_weight_input($item, $type) {
1c1f64a2 371 global $OUTPUT;
372
dc482cfa 373 if (!is_object($item) || get_class($item) !== 'grade_item') {
374 throw new Exception('grade_edit_tree::get_weight_input($item) was given a variable that is not of the required type (grade_item object)');
375 return false;
376 }
377
378 if ($item->is_course_item()) {
379 return '';
380 }
381
382 $parent_category = $item->get_parent_category();
dc482cfa 383 $parent_category->apply_forced_settings();
653a8648 384 $aggcoef = $item->get_coefstring();
dc482cfa 385
653a8648 386 if ((($aggcoef == 'aggregationcoefweight' || $aggcoef == 'aggregationcoef') && $type == 'weight') ||
3869ab1a 387 ($aggcoef == 'aggregationcoefextraweight' && $type == 'extra')) {
7400be1b
RT
388 return '<label class="accesshide" for="aggregationcoef_'.$item->id.'">'.
389 get_string('extracreditvalue', 'grades', $item->itemname).'</label>'.
b1fec412 390 '<input type="text" size="6" id="aggregationcoef_'.$item->id.'" name="aggregationcoef_'.$item->id.'"
3cf33f51 391 value="'.grade_edit_tree::format_number($item->aggregationcoef).'" />';
653a8648 392 } elseif ($aggcoef == 'aggregationcoefextrasum' && $type == 'extra') {
cd3a391c 393 $checked = ($item->aggregationcoef > 0) ? 'checked="checked"' : '';
916276fc 394 return '<input type="hidden" name="extracredit_'.$item->id.'" value="0" />
7400be1b
RT
395 <label class="accesshide" for="extracredit_'.$item->id.'">'.
396 get_string('extracreditvalue', 'grades', $item->itemname).'</label>
397 <input type="checkbox" id="extracredit_'.$item->id.'" name="extracredit_'.$item->id.'" value="1" '."$checked />\n";
677bc073 398 } else if ($aggcoef == 'aggregationcoefextrasum' && $type == 'weight') {
45da5361 399 $label = '';
b14c5870 400 if ($item->weightoverride && $parent_category->aggregation == GRADE_AGGREGATE_SUM) {
45da5361
AD
401 $label = get_string('adjusted', 'grades');
402 }
677bc073
JO
403 return '<label class="accesshide" for="aggregationcoef_'.$item->id.'">'.
404 get_string('weight', 'grades', $item->itemname).'</label>'.
405 '<input type="text" size="6" id="aggregationcoef2_'.$item->id.'" name="aggregationcoef2_'.$item->id.'"
45da5361 406 value="'.grade_edit_tree::format_number($item->aggregationcoef2).'" />'.$label;
cd3a391c 407 } else {
408 return '';
dc482cfa 409 }
cd3a391c 410 }
dc482cfa 411
6ef4878b 412 //Trims trailing zeros
4592df46 413 //Used on the 'categories and items' page for grade items settings like aggregation co-efficient
e229506d 414 //Grader report has its own decimal place settings so they are handled elsewhere
e2bb3c92 415 static function format_number($number) {
4592df46 416 $formatted = rtrim(format_float($number, 4),'0');
dacd5daa 417 if (substr($formatted, -1)==get_string('decsep', 'langconfig')) { //if last char is the decimal point
4592df46
AD
418 $formatted .= '0';
419 }
420 return $formatted;
3cf33f51
AD
421 }
422
dc482cfa 423 /**
424 * Given an element of the grade tree, returns whether it is deletable or not (only manual grade items are deletable)
425 *
426 * @param array $element
427 * @return bool
428 */
429 function element_deletable($element) {
430 global $COURSE;
431
432 if ($element['type'] != 'item') {
433 return true;
434 }
435
436 $grade_item = $element['object'];
437
438 if ($grade_item->itemtype != 'mod' or $grade_item->is_outcome_item() or $grade_item->gradetype == GRADE_TYPE_NONE) {
439 return true;
440 }
441
442 $modinfo = get_fast_modinfo($COURSE);
443 if (!isset($modinfo->instances[$grade_item->itemmodule][$grade_item->iteminstance])) {
444 // module does not exist
445 return true;
446 }
447
448 return false;
449 }
450
451 /**
452 * Given the grade tree and an array of element ids (e.g. c15, i42), and expecting the 'moveafter' URL param,
453 * moves the selected items to the requested location. Then redirects the user to the given $returnurl
454 *
455 * @param object $gtree The grade tree (a recursive representation of the grade categories and grade items)
456 * @param array $eids
457 * @param string $returnurl
458 */
459 function move_elements($eids, $returnurl) {
460 $moveafter = required_param('moveafter', PARAM_INT);
461
462 if (!is_array($eids)) {
463 $eids = array($eids);
464 }
465
466 if(!$after_el = $this->gtree->locate_element("c$moveafter")) {
467 print_error('invalidelementid', '', $returnurl);
468 }
469
470 $after = $after_el['object'];
471 $parent = $after;
472 $sortorder = $after->get_sortorder();
473
474 foreach ($eids as $eid) {
475 if (!$element = $this->gtree->locate_element($eid)) {
476 print_error('invalidelementid', '', $returnurl);
477 }
478 $object = $element['object'];
479
480 $object->set_parent($parent->id);
481 $object->move_after_sortorder($sortorder);
4d2f7923 482 $sortorder++;
dc482cfa 483 }
484
485 redirect($returnurl, '', 0);
486 }
487
488 /**
489 * Recurses through the entire grade tree to find and return the maximum depth of the tree.
490 * This should be run only once from the root element (course category), and is used for the
491 * indentation of the Name column's cells (colspan)
492 *
493 * @param array $element An array of values representing a grade tree's element (all grade items in this case)
494 * @param int $level The level of the current recursion
495 * @param int $deepest_level A value passed to each subsequent level of recursion and incremented if $level > $deepest_level
496 * @return int Deepest level
497 */
498 function get_deepest_level($element, $level=0, $deepest_level=1) {
499 $object = $element['object'];
500
501 $level++;
653a8648 502 $coefstring = $element['object']->get_coefstring();
dc482cfa 503 if ($element['type'] == 'category') {
653a8648 504 if ($coefstring == 'aggregationcoefweight') {
505 $this->uses_weight = true;
3869ab1a 506 } elseif ($coefstring == 'aggregationcoefextraweight' || $coefstring == 'aggregationcoefextrasum') {
653a8648 507 $this->uses_extra_credit = true;
508 }
677bc073
JO
509 if ($coefstring == 'aggregationcoefextrasum') { // TODO: coefstring2?
510 $this->uses_weight2 = true;
511 }
653a8648 512
dc482cfa 513 foreach($element['children'] as $child_el) {
514 if ($level > $deepest_level) {
515 $deepest_level = $level;
516 }
517 $deepest_level = $this->get_deepest_level($child_el, $level, $deepest_level);
518 }
519 }
520
521 return $deepest_level;
522 }
523}
524
525abstract class grade_edit_tree_column {
526 public $forced;
527 public $hidden;
528 public $forced_hidden;
529 public $advanced_hidden;
530 public $hide_when_moving = true;
54a007e8 531 /**
532 * html_table_cell object used as a template for header cells in all categories.
533 * It must be cloned before being used.
534 * @var html_table_cell $headercell
535 */
536 public $headercell;
537 /**
538 * html_table_cell object used as a template for category cells in all categories.
539 * It must be cloned before being used.
540 * @var html_table_cell $categorycell
541 */
542 public $categorycell;
543 /**
544 * html_table_cell object used as a template for item cells in all categories.
545 * It must be cloned before being used.
546 * @var html_table_cell $itemcell
547 */
548 public $itemcell;
dc482cfa 549
550 public static function factory($name, $params=array()) {
551 $class_name = "grade_edit_tree_column_$name";
552 if (class_exists($class_name)) {
553 return new $class_name($params);
554 }
555 }
556
557 public abstract function get_header_cell();
558
559 public abstract function get_category_cell($category, $levelclass, $params);
560
561 public abstract function get_item_cell($item, $params);
562
563 public abstract function is_hidden($mode='simple');
54a007e8 564
565 public function __construct() {
566 $this->headercell = new html_table_cell();
567 $this->headercell->header = true;
568 $this->headercell->style = 'whitespace: normal;';
16be8974 569 $this->headercell->attributes['class'] = 'header';
54a007e8 570
571 $this->categorycell = new html_table_cell();
16be8974 572 $this->categorycell->attributes['class'] = 'cell';
54a007e8 573
574 $this->itemcell = new html_table_cell();
16be8974 575 $this->itemcell->attributes['class'] = 'cell';
54a007e8 576 }
dc482cfa 577}
578
579abstract class grade_edit_tree_column_category extends grade_edit_tree_column {
580
581 public $forced;
582 public $advanced;
583
584 public function __construct($name) {
585 global $CFG;
586 $this->forced = (int)$CFG->{"grade_$name"."_flag"} & 1;
587 $this->advanced = (int)$CFG->{"grade_$name"."_flag"} & 2;
54a007e8 588 parent::__construct();
dc482cfa 589 }
590
591 public function is_hidden($mode='simple') {
592 global $CFG;
593 if ($mode == 'simple') {
594 return $this->advanced;
595 } elseif ($mode == 'advanced') {
596 if ($this->forced && $CFG->grade_hideforcedsettings) {
597 return true;
598 } else {
599 return false;
600 }
601 }
602 }
603}
604
605class grade_edit_tree_column_name extends grade_edit_tree_column {
606 public $forced = false;
607 public $hidden = false;
608 public $forced_hidden = false;
609 public $advanced_hidden = false;
610 public $deepest_level = 1;
611 public $hide_when_moving = false;
612
613 public function __construct($params) {
614 if (empty($params['deepest_level'])) {
615 throw new Exception('Tried to instantiate a grade_edit_tree_column_name object without the "deepest_level" param!');
616 }
617
618 $this->deepest_level = $params['deepest_level'];
54a007e8 619 parent::__construct();
dc482cfa 620 }
621
622 public function get_header_cell() {
54a007e8 623 $headercell = clone($this->headercell);
16be8974 624 $headercell->attributes['class'] .= ' name';
54a007e8 625 $headercell->colspan = $this->deepest_level + 1;
626 $headercell->text = get_string('name');
627 return $headercell;
dc482cfa 628 }
629
630 public function get_category_cell($category, $levelclass, $params) {
54a007e8 631 global $OUTPUT;
dc482cfa 632 if (empty($params['name']) || empty($params['level'])) {
633 throw new Exception('Array key (name or level) missing from 3rd param of grade_edit_tree_column_name::get_category_cell($category, $levelclass, $params)');
634 }
54a007e8 635 $categorycell = clone($this->categorycell);
16be8974 636 $categorycell->attributes['class'] .= ' name ' . $levelclass;
54a007e8 637 $categorycell->colspan = ($this->deepest_level +1) - $params['level'];
638 $categorycell->text = $OUTPUT->heading($params['name'], 4);
639 return $categorycell;
dc482cfa 640 }
641
642 public function get_item_cell($item, $params) {
643 global $CFG;
644
645 if (empty($params['element']) || empty($params['name']) || empty($params['level'])) {
646 throw new Exception('Array key (name, level or element) missing from 2nd param of grade_edit_tree_column_name::get_item_cell($item, $params)');
647 }
648
649 $name = $params['name'];
650
54a007e8 651 $itemcell = clone($this->itemcell);
16be8974 652 $itemcell->attributes['class'] .= ' name';
54a007e8 653 $itemcell->colspan = ($this->deepest_level + 1) - $params['level'];
654 $itemcell->text = $name;
655 return $itemcell;
dc482cfa 656 }
657
658 public function is_hidden($mode='simple') {
659 return false;
660 }
661}
662
663class grade_edit_tree_column_aggregation extends grade_edit_tree_column_category {
664
665 public function __construct($params) {
666 parent::__construct('aggregation');
667 }
668
669 public function get_header_cell() {
c3b834b4 670 global $OUTPUT;
54a007e8 671 $headercell = clone($this->headercell);
f89b71eb 672 $headercell->text = get_string('aggregation', 'grades').$OUTPUT->help_icon('aggregation', 'grades');
54a007e8 673 return $headercell;
dc482cfa 674 }
675
676 public function get_category_cell($category, $levelclass, $params) {
0a95bebf 677 global $CFG, $OUTPUT;
dc482cfa 678 if (empty($params['id'])) {
679 throw new Exception('Array key (id) missing from 3rd param of grade_edit_tree_column_aggregation::get_category_cell($category, $levelclass, $params)');
680 }
681
bfe969e8 682 $options = grade_helper::get_aggregation_strings();
dc482cfa 683
653a8648 684 $visible = explode(',', $CFG->grade_aggregations_visible);
685 foreach ($options as $constant => $string) {
686 if (!in_array($constant, $visible) && $constant != $category->aggregation) {
687 unset($options[$constant]);
688 }
689 }
690
dc482cfa 691 if ($this->forced) {
692 $aggregation = $options[$category->aggregation];
064527d6
PS
693 } else {
694 $attributes = array();
695 $attributes['id'] = 'aggregation_'.$category->id;
742d9165 696 $attributes['class'] = 'ignoredirty';
29bea634
RW
697 $aggregation = html_writer::label(get_string('aggregation', 'grades'), 'aggregation_'.$category->id, false, array('class' => 'accesshide'));
698 $aggregation .= html_writer::select($options, 'aggregation_'.$category->id, $category->aggregation, null, $attributes);
064527d6 699 $action = new component_action('change', 'update_category_aggregation', array('courseid' => $params['id'], 'category' => $category->id, 'sesskey' => sesskey()));
c80877aa 700 $OUTPUT->add_action_handler($action, 'aggregation_'.$category->id);
dc482cfa 701 }
702
54a007e8 703 $categorycell = clone($this->categorycell);
16be8974 704 $categorycell->attributes['class'] .= ' ' . $levelclass;
54a007e8 705 $categorycell->text = $aggregation;
706 return $categorycell;
dc482cfa 707
708 }
709
710 public function get_item_cell($item, $params) {
54a007e8 711 $itemcell = clone($this->itemcell);
712 $itemcell->text = ' - ';
713 return $itemcell;
dc482cfa 714 }
715}
716
653a8648 717class grade_edit_tree_column_extracredit extends grade_edit_tree_column {
718
719 public function get_header_cell() {
c3b834b4 720 global $OUTPUT;
54a007e8 721 $headercell = clone($this->headercell);
3869ab1a 722 $headercell->text = get_string('aggregationcoefextra', 'grades').$OUTPUT->help_icon('aggregationcoefextra', 'grades');
54a007e8 723 return $headercell;
653a8648 724 }
725
726 public function get_category_cell($category, $levelclass, $params) {
653a8648 727 $item = $category->get_grade_item();
54a007e8 728 $categorycell = clone($this->categorycell);
16be8974 729 $categorycell->attributes['class'] .= ' ' . $levelclass;
54a007e8 730 $categorycell->text = grade_edit_tree::get_weight_input($item, 'extra');
731 return $categorycell;
653a8648 732 }
733
734 public function get_item_cell($item, $params) {
735 if (empty($params['element'])) {
736 throw new Exception('Array key (element) missing from 2nd param of grade_edit_tree_column_weightorextracredit::get_item_cell($item, $params)');
737 }
738
54a007e8 739 $itemcell = clone($this->itemcell);
740 $itemcell->text = '&nbsp;';
653a8648 741
742 if (!in_array($params['element']['object']->itemtype, array('courseitem', 'categoryitem', 'category'))) {
54a007e8 743 $itemcell->text = grade_edit_tree::get_weight_input($item, 'extra');
653a8648 744 }
745
54a007e8 746 return $itemcell;
653a8648 747 }
748
749 public function is_hidden($mode='simple') {
750 global $CFG;
751 if ($mode == 'simple') {
752 return strstr($CFG->grade_item_advanced, 'aggregationcoef');
753 } elseif ($mode == 'advanced') {
754 return false;
755 }
756 }
757}
758
759class grade_edit_tree_column_weight extends grade_edit_tree_column {
dc482cfa 760
761 public function get_header_cell() {
c3b834b4 762 global $OUTPUT;
54a007e8 763 $headercell = clone($this->headercell);
bfe969e8 764 $headercell->text = get_string('weights', 'grades').$OUTPUT->help_icon('aggregationcoefweight', 'grades');
54a007e8 765 return $headercell;
dc482cfa 766 }
767
768 public function get_category_cell($category, $levelclass, $params) {
769
770 $item = $category->get_grade_item();
54a007e8 771 $categorycell = clone($this->categorycell);
16be8974 772 $categorycell->attributes['class'] .= ' ' . $levelclass;
54a007e8 773 $categorycell->text = grade_edit_tree::get_weight_input($item, 'weight');
774 return $categorycell;
dc482cfa 775 }
776
777 public function get_item_cell($item, $params) {
778 if (empty($params['element'])) {
779 throw new Exception('Array key (element) missing from 2nd param of grade_edit_tree_column_weightorextracredit::get_item_cell($item, $params)');
780 }
54a007e8 781 $itemcell = clone($this->itemcell);
782 $itemcell->text = '&nbsp;';
dc482cfa 783
b8436ccb 784 if (!in_array($params['element']['object']->itemtype, array('courseitem', 'categoryitem', 'category'))) {
54a007e8 785 $itemcell->text = grade_edit_tree::get_weight_input($item, 'weight');
dc482cfa 786 }
787
54a007e8 788 return $itemcell;
dc482cfa 789 }
790
791 public function is_hidden($mode='simple') {
792 global $CFG;
793 if ($mode == 'simple') {
794 return strstr($CFG->grade_item_advanced, 'aggregationcoef');
795 } elseif ($mode == 'advanced') {
796 return false;
797 }
798 }
799}
800
801class grade_edit_tree_column_range extends grade_edit_tree_column {
802
803 public function get_header_cell() {
54a007e8 804 $headercell = clone($this->headercell);
805 $headercell->text = get_string('maxgrade', 'grades');
806 return $headercell;
dc482cfa 807 }
808
809 public function get_category_cell($category, $levelclass, $params) {
54a007e8 810 $categorycell = clone($this->categorycell);
16be8974 811 $categorycell->attributes['class'] .= ' range ' . $levelclass;
54a007e8 812 $categorycell->text = ' - ';
813 return $categorycell;
dc482cfa 814 }
815
816 public function get_item_cell($item, $params) {
1c1f64a2 817 global $DB, $OUTPUT;
46409b20 818
b5e00814 819 // If the parent aggregation is Natural, we should show the number, even for scales, as that value is used...
e3a65c9e 820 // ...in the computation. For text grades, the grademax is not used, so we can still show the no value string.
46409b20 821 $parent_cat = $item->get_parent_category();
e3a65c9e
EM
822 if ($item->gradetype == GRADE_TYPE_TEXT) {
823 $grademax = ' - ';
824 } else if ($parent_cat->aggregation == GRADE_AGGREGATE_SUM) {
46409b20 825 $grademax = format_float($item->grademax, $item->get_decimals());
826 } elseif ($item->gradetype == GRADE_TYPE_SCALE) {
3998cc5c 827 $scale = $DB->get_record('scale', array('id' => $item->scaleid));
e2a84477
AD
828 $scale_items = null;
829 if (empty($scale)) { //if the item is using a scale that's been removed
830 $scale_items = array();
831 } else {
832 $scale_items = explode(',', $scale->scale);
833 }
dc482cfa 834 $grademax = end($scale_items) . ' (' . count($scale_items) . ')';
835 } elseif ($item->is_external_item()) {
836 $grademax = format_float($item->grademax, $item->get_decimals());
837 } else {
7400be1b
RT
838 $grademax = '<label class="accesshide" for="grademax'.$item->id.'">'.get_string('grademax', 'grades').'</label>
839 <input type="text" size="6" id="grademax'.$item->id.'" name="grademax_'.$item->id.'" value="'.
840 format_float($item->grademax, $item->get_decimals()).'" />';
dc482cfa 841 }
842
54a007e8 843 $itemcell = clone($this->itemcell);
844 $itemcell->text = $grademax;
845 return $itemcell;
dc482cfa 846 }
847
848 public function is_hidden($mode='simple') {
849 global $CFG;
850 if ($mode == 'simple') {
851 return strstr($CFG->grade_item_advanced, 'grademax');
852 } elseif ($mode == 'advanced') {
853 return false;
854 }
855 }
856}
857
858class grade_edit_tree_column_aggregateonlygraded extends grade_edit_tree_column_category {
859
860 public function __construct($params) {
861 parent::__construct('aggregateonlygraded');
862 }
863
864 public function get_header_cell() {
c3b834b4 865 global $OUTPUT;
54a007e8 866 $headercell = clone($this->headercell);
867 $headercell->style .= 'width: 40px;';
71297a3f 868 $headercell->text = get_string('aggregateonlygraded', 'grades')
be3df7fb 869 . $OUTPUT->help_icon('aggregateonlygraded', 'grades');
54a007e8 870 return $headercell;
dc482cfa 871 }
872
873 public function get_category_cell($category, $levelclass, $params) {
916276fc
PS
874 $onlygradedcheck = ($category->aggregateonlygraded == 1) ? 'checked="checked"' : '';
875 $hidden = '<input type="hidden" name="aggregateonlygraded_'.$category->id.'" value="0" />';
7400be1b
RT
876 $aggregateonlygraded = '<label class="accesshide" for="aggregateonlygraded_'.$category->id.'">'.
877 get_string('aggregateonlygraded', 'grades').'</label>
878 <input type="checkbox" id="aggregateonlygraded_'.$category->id.'" name="aggregateonlygraded_'.
879 $category->id.'" value="1" '.$onlygradedcheck . ' />';
dc482cfa 880
881 if ($this->forced) {
882 $aggregateonlygraded = ($category->aggregateonlygraded) ? get_string('yes') : get_string('no');
883 }
884
54a007e8 885 $categorycell = clone($this->categorycell);
16be8974 886 $categorycell->attributes['class'] .= ' ' . $levelclass;
916276fc 887 $categorycell->text = $hidden.$aggregateonlygraded;
54a007e8 888 return $categorycell;
dc482cfa 889 }
890
891 public function get_item_cell($item, $params) {
54a007e8 892 $itemcell = clone($this->itemcell);
893 $itemcell->text = ' - ';
894 return $itemcell;
dc482cfa 895 }
896}
897
898class grade_edit_tree_column_aggregatesubcats extends grade_edit_tree_column_category {
899
900 public function __construct($params) {
901 parent::__construct('aggregatesubcats');
902 }
903
904 public function get_header_cell() {
c3b834b4 905 global $OUTPUT;
54a007e8 906 $headercell = clone($this->headercell);
907 $headercell->style .= 'width: 40px;';
908 $headercell->text = get_string('aggregatesubcats', 'grades')
cb616be8 909 .$OUTPUT->help_icon('aggregatesubcats', 'grades');
54a007e8 910 return $headercell;
dc482cfa 911 }
912
913 public function get_category_cell($category, $levelclass, $params) {
916276fc
PS
914 $subcatscheck = ($category->aggregatesubcats == 1) ? 'checked="checked"' : '';
915 $hidden = '<input type="hidden" name="aggregatesubcats_'.$category->id.'" value="0" />';
7400be1b
RT
916 $aggregatesubcats = '<label class="accesshide" for="aggregatesubcats_'.$category->id.'">'.
917 get_string('aggregatesubcats', 'grades').'</label>
918 <input type="checkbox" id="aggregatesubcats_'.$category->id.'" name="aggregatesubcats_'.$category->id.
919 '" value="1" ' . $subcatscheck.' />';
dc482cfa 920
921 if ($this->forced) {
922 $aggregatesubcats = ($category->aggregatesubcats) ? get_string('yes') : get_string('no');
923 }
924
54a007e8 925 $categorycell = clone($this->categorycell);
16be8974 926 $categorycell->attributes['class'] .= ' ' . $levelclass;
916276fc 927 $categorycell->text = $hidden.$aggregatesubcats;
54a007e8 928 return $categorycell;
dc482cfa 929
930 }
931
932 public function get_item_cell($item, $params) {
54a007e8 933 $itemcell = clone($this->itemcell);
934 $itemcell->text = ' - ';
935 return $itemcell;
dc482cfa 936 }
937}
938
939class grade_edit_tree_column_aggregateoutcomes extends grade_edit_tree_column_category {
940
941 public function __construct($params) {
942 parent::__construct('aggregateoutcomes');
943 }
944
945 public function get_header_cell() {
c3b834b4 946 global $OUTPUT;
54a007e8 947 $headercell = clone($this->headercell);
948 $headercell->style .= 'width: 40px;';
949 $headercell->text = get_string('aggregateoutcomes', 'grades')
3f781a22 950 .$OUTPUT->help_icon('aggregateoutcomes', 'grades');
54a007e8 951 return $headercell;
dc482cfa 952 }
953
954 public function get_category_cell($category, $levelclass, $params) {
916276fc
PS
955 $outcomescheck = ($category->aggregateoutcomes == 1) ? 'checked="checked"' : '';
956 $hidden = '<input type="hidden" name="aggregateoutcomes_'.$category->id.'" value="0" />';
7400be1b
RT
957 $aggregateoutcomes = '<label class="accesshide" for="aggregateoutcomes_'.$category->id.'">'.
958 get_string('aggregateoutcomes', 'grades').'</label>
959 <input type="checkbox" id="aggregateoutcomes_'.$category->id.'" name="aggregateoutcomes_'.$category->id.
960 '" value="1" ' . $outcomescheck.' />';
dc482cfa 961
962 if ($this->forced) {
963 $aggregateoutcomes = ($category->aggregateoutcomes) ? get_string('yes') : get_string('no');
964 }
965
54a007e8 966 $categorycell = clone($this->categorycell);
16be8974 967 $categorycell->attributes['class'] .= ' ' . $levelclass;
916276fc 968 $categorycell->text = $hidden.$aggregateoutcomes;
54a007e8 969 return $categorycell;
dc482cfa 970 }
971
972 public function get_item_cell($item, $params) {
54a007e8 973 $itemcell = clone($this->itemcell);
974 $itemcell->text = ' - ';
975 return $itemcell;
dc482cfa 976 }
977
978 public function is_hidden($mode='simple') {
979 global $CFG;
980 if ($CFG->enableoutcomes) {
981 return parent::is_hidden($mode);
982 } else {
983 return true;
984 }
985 }
986}
987
988class grade_edit_tree_column_droplow extends grade_edit_tree_column_category {
989
990 public function __construct($params) {
991 parent::__construct('droplow');
992 }
993
994 public function get_header_cell() {
c3b834b4 995 global $OUTPUT;
54a007e8 996 $headercell = clone($this->headercell);
b37760fc 997 $headercell->text = get_string('droplow', 'grades').$OUTPUT->help_icon('droplow', 'grades');
54a007e8 998 return $headercell;
dc482cfa 999 }
1000
1001 public function get_category_cell($category, $levelclass, $params) {
7400be1b
RT
1002 $droplow = '<label class="accesshide" for="droplow_' . $category->id.'">' . get_string('droplowestvalue', 'grades') . '</label>';
1003 $droplow .= '<input type="text" size="3" id="droplow_' . $category->id . '" name="droplow_' . $category->id . '" value="'
1004 . $category->droplow.'" />';
dc482cfa 1005
1006 if ($this->forced) {
1007 $droplow = $category->droplow;
1008 }
1009
54a007e8 1010 $categorycell = clone($this->categorycell);
16be8974 1011 $categorycell->attributes['class'] .= ' ' . $levelclass;
54a007e8 1012 $categorycell->text = $droplow;
1013 return $categorycell;
dc482cfa 1014 }
1015
1016 public function get_item_cell($item, $params) {
54a007e8 1017 $itemcell = clone($this->itemcell);
1018 $itemcell->text = ' - ';
1019 return $itemcell;
dc482cfa 1020 }
1021}
1022
1023class grade_edit_tree_column_keephigh extends grade_edit_tree_column_category {
1024
1025 public function __construct($params) {
1026 parent::__construct('keephigh');
1027 }
1028
1029 public function get_header_cell() {
c3b834b4 1030 global $OUTPUT;
54a007e8 1031 $headercell = clone($this->headercell);
cb616be8 1032 $headercell->text = get_string('keephigh', 'grades').$OUTPUT->help_icon('keephigh', 'grades');
54a007e8 1033 return $headercell;
dc482cfa 1034 }
1035
1036 public function get_category_cell($category, $levelclass, $params) {
b1fec412 1037 $keephigh = '<label class="accesshide" for="keephigh_'.$category->id.'">'.get_string('keephigh', 'grades').'</label>';
7400be1b
RT
1038 $keephigh .= '<input type="text" size="3" id="keephigh_'.$category->id.'" name="keephigh_'.$category->id.'" value="'.
1039 $category->keephigh.'" />';
dc482cfa 1040
1041 if ($this->forced) {
1042 $keephigh = $category->keephigh;
1043 }
1044
54a007e8 1045 $categorycell = clone($this->categorycell);
16be8974 1046 $categorycell->attributes['class'] .= ' ' . $levelclass;
54a007e8 1047 $categorycell->text = $keephigh;
1048 return $categorycell;
dc482cfa 1049 }
1050
1051 public function get_item_cell($item, $params) {
54a007e8 1052 $itemcell = clone($this->itemcell);
1053 $itemcell->text = ' - ';
1054 return $itemcell;
dc482cfa 1055 }
1056}
1057
1058class grade_edit_tree_column_multfactor extends grade_edit_tree_column {
1059
1060 public function __construct($params) {
54a007e8 1061 parent::__construct();
dc482cfa 1062 }
1063
1064 public function get_header_cell() {
c3b834b4 1065 global $OUTPUT;
54a007e8 1066 $headercell = clone($this->headercell);
d4a11ee5 1067 $headercell->text = get_string('multfactor', 'grades').$OUTPUT->help_icon('multfactor', 'grades');
54a007e8 1068 return $headercell;
dc482cfa 1069 }
1070
1071 public function get_category_cell($category, $levelclass, $params) {
54a007e8 1072 $categorycell = clone($this->categorycell);
16be8974 1073 $categorycell->attributes['class'] .= ' ' . $levelclass;
54a007e8 1074 $categorycell->text = ' - ';
1075 return $categorycell;
dc482cfa 1076 }
1077
1078 public function get_item_cell($item, $params) {
54a007e8 1079 global $OUTPUT;
1080
1081 $itemcell = clone($this->itemcell);
a043086f 1082 if (!$item->is_raw_used()) {
54a007e8 1083 $itemcell->text = '&nbsp;';
1084 return $itemcell;
a043086f 1085 }
7400be1b
RT
1086 $multfactor = '<label class="accesshide" for="multfactor'.$item->id.'">'.
1087 get_string('multfactorvalue', 'grades', $item->itemname).'</label>
1088 <input type="text" size="4" id="multfactor'.$item->id.'" name="multfactor_'.$item->id.'" value="'.
1089 grade_edit_tree::format_number($item->multfactor).'" />';
54a007e8 1090
7d89f0b0 1091 $itemcell->text = $multfactor;
54a007e8 1092 return $itemcell;
dc482cfa 1093 }
1094
1095 public function is_hidden($mode='simple') {
1096 global $CFG;
1097 if ($mode == 'simple') {
1098 return strstr($CFG->grade_item_advanced, 'multfactor');
1099 } elseif ($mode == 'advanced') {
1100 return false;
1101 }
1102 }
1103}
1104
1105class grade_edit_tree_column_plusfactor extends grade_edit_tree_column {
1106
1107 public function get_header_cell() {
c3b834b4 1108 global $OUTPUT;
54a007e8 1109 $headercell = clone($this->headercell);
12b0938c 1110 $headercell->text = get_string('plusfactor', 'grades').$OUTPUT->help_icon('plusfactor', 'grades');
54a007e8 1111 return $headercell;
dc482cfa 1112 }
1113
1114 public function get_category_cell($category, $levelclass, $params) {
54a007e8 1115 $categorycell = clone($this->categorycell);
16be8974 1116 $categorycell->attributes['class'] .= ' ' . $levelclass;
54a007e8 1117 $categorycell->text = ' - ';
1118 return $categorycell;
dc482cfa 1119
1120 }
1121
1122 public function get_item_cell($item, $params) {
54a007e8 1123 global $OUTPUT;
1124
1125 $itemcell = clone($this->itemcell);
a043086f 1126 if (!$item->is_raw_used()) {
54a007e8 1127 $itemcell->text = '&nbsp;';
1128 return $itemcell;
a043086f 1129 }
54a007e8 1130
7400be1b
RT
1131 $plusfactor = '<label class="accesshide" for="plusfactor_'. $item->id . '">'.
1132 get_string('plusfactorvalue', 'grades', $item->itemname).'</label>
1133 <input type="text" size="4" id="plusfactor_'.$item->id.'" name="plusfactor_'.$item->id.'" value="'.
1134 grade_edit_tree::format_number($item->plusfactor).'" />';
916276fc 1135
7d89f0b0 1136 $itemcell->text = $plusfactor;
54a007e8 1137 return $itemcell;
dc482cfa 1138
1139 }
1140
1141 public function is_hidden($mode='simple') {
1142 global $CFG;
1143 if ($mode == 'simple') {
1144 return strstr($CFG->grade_item_advanced, 'plusfactor');
1145 } elseif ($mode == 'advanced') {
1146 return false;
1147 }
1148 }
1149}
1150
1151class grade_edit_tree_column_actions extends grade_edit_tree_column {
1152
1153 public function __construct($params) {
71297a3f 1154 parent::__construct();
dc482cfa 1155 }
1156
1157 public function get_header_cell() {
54a007e8 1158 $headercell = clone($this->headercell);
16be8974 1159 $headercell->attributes['class'] .= ' actions';
54a007e8 1160 $headercell->text = get_string('actions');
1161 return $headercell;
dc482cfa 1162 }
1163
1164 public function get_category_cell($category, $levelclass, $params) {
1165
1166 if (empty($params['actions'])) {
1167 throw new Exception('Array key (actions) missing from 3rd param of grade_edit_tree_column_actions::get_category_actions($category, $levelclass, $params)');
1168 }
1169
54a007e8 1170 $categorycell = clone($this->categorycell);
16be8974 1171 $categorycell->attributes['class'] .= ' ' . $levelclass;
54a007e8 1172 $categorycell->text = $params['actions'];
1173 return $categorycell;
dc482cfa 1174 }
1175
1176 public function get_item_cell($item, $params) {
1177 if (empty($params['actions'])) {
1178 throw new Exception('Array key (actions) missing from 2nd param of grade_edit_tree_column_actions::get_item_cell($item, $params)');
1179 }
54a007e8 1180 $itemcell = clone($this->itemcell);
16be8974 1181 $itemcell->attributes['class'] .= ' actions';
54a007e8 1182 $itemcell->text = $params['actions'];
1183 return $itemcell;
dc482cfa 1184 }
1185
1186 public function is_hidden($mode='simple') {
1187 return false;
1188 }
1189}
1190
1191class grade_edit_tree_column_select extends grade_edit_tree_column {
1192
1193 public function get_header_cell() {
54a007e8 1194 $headercell = clone($this->headercell);
16be8974 1195 $headercell->attributes['class'] .= ' selection';
54a007e8 1196 $headercell->text = get_string('select');
1197 return $headercell;
dc482cfa 1198 }
1199
1200 public function get_category_cell($category, $levelclass, $params) {
54a007e8 1201 global $OUTPUT;
dc482cfa 1202 if (empty($params['eid'])) {
1203 throw new Exception('Array key (eid) missing from 3rd param of grade_edit_tree_column_select::get_category_cell($category, $levelclass, $params)');
1204 }
4ee753eb
PS
1205 $selectall = new action_link(new moodle_url('#'), get_string('all'), new component_action('click', 'togglecheckboxes', array('eid' => $params['eid'], 'check' => true)));
1206 $selectnone = new action_link(new moodle_url('#'), get_string('none'), new component_action('click', 'togglecheckboxes', array('eid' => $params['eid'], 'check' => false)));
dc482cfa 1207
54a007e8 1208 $categorycell = clone($this->categorycell);
16be8974 1209 $categorycell->attributes['class'] .= ' last ' . $levelclass;
54a007e8 1210 $categorycell->style .= 'text-align: center;';
4ee753eb 1211 $categorycell->text = $OUTPUT->render($selectall) . '<br />' . $OUTPUT->render($selectnone);
54a007e8 1212 return $categorycell;
dc482cfa 1213 }
1214
1215 public function get_item_cell($item, $params) {
54a007e8 1216 if (empty($params['itemtype']) || empty($params['eid'])) {
2f0e96e4 1217 error('Array key (itemtype or eid) missing from 2nd param of grade_edit_tree_column_select::get_item_cell($item, $params)');
54a007e8 1218 }
1219 $itemselect = '';
1220
1221 if ($params['itemtype'] != 'course' && $params['itemtype'] != 'category') {
7400be1b
RT
1222 $itemselect = '<label class="accesshide" for="select_'.$params['eid'].'">'.
1223 get_string('select', 'grades', $item->itemname).'</label>
ef93efbf 1224 <input class="itemselect ignoredirty" type="checkbox" name="select_'.$params['eid'].'" id="select_'.$params['eid'].
7400be1b 1225 '" onchange="toggleCategorySelector();"/>'; // TODO: convert to YUI handler
dc482cfa 1226 }
5174f3c5
AD
1227 //html_writer::table() will wrap the item cell contents in a <TD> so don't do it here
1228 return $itemselect;
dc482cfa 1229 }
1230
1231 public function is_hidden($mode='simple') {
1232 return false;
1233 }
1234}
6c3ef410 1235