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