MDL-66999 theme_boost: @extend remove extends for grades
[moodle.git] / grade / grading / form / rubric / renderer.php
CommitLineData
c586d2bf 1<?php
c586d2bf
MG
2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16
17/**
d22e9e32
MG
18 * Contains renderer used for displaying rubric
19 *
20 * @package gradingform_rubric
c586d2bf
MG
21 * @copyright 2011 Marina Glancy
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24
c586d2bf
MG
25defined('MOODLE_INTERNAL') || die();
26
27/**
28 * Grading method plugin renderer
d22e9e32 29 *
5dc1ca87 30 * @package gradingform_rubric
d22e9e32
MG
31 * @copyright 2011 Marina Glancy
32 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
c586d2bf 33 */
2ae7faf1 34class gradingform_rubric_renderer extends plugin_renderer_base {
c586d2bf 35
ab156741 36 /**
fc5adc3b
MG
37 * This function returns html code for displaying criterion. Depending on $mode it may be the
38 * code to edit rubric, to preview the rubric, to evaluate somebody or to review the evaluation.
39 *
40 * This function may be called from display_rubric() to display the whole rubric, or it can be
41 * called by itself to return a template used by JavaScript to add new empty criteria to the
42 * rubric being designed.
43 * In this case it will use macros like {NAME}, {LEVELS}, {CRITERION-id}, etc.
44 *
45 * When overriding this function it is very important to remember that all elements of html
46 * form (in edit or evaluate mode) must have the name $elementname.
ab156741 47 *
fc5adc3b
MG
48 * Also JavaScript relies on the class names of elements and when developer changes them
49 * script might stop working.
50 *
d22e9e32
MG
51 * @param int $mode rubric display mode, see {@link gradingform_rubric_controller}
52 * @param array $options display options for this rubric, defaults are: {@link gradingform_rubric_controller::get_default_options()}
fc5adc3b
MG
53 * @param string $elementname the name of the form element (in editor mode) or the prefix for div ids (in view mode)
54 * @param array|null $criterion criterion data
3c2b3cb3 55 * @param string $levelsstr evaluated templates for this criterion levels
fc5adc3b 56 * @param array|null $value (only in view mode) teacher's feedback on this criterion
ab156741
MG
57 * @return string
58 */
3c2b3cb3 59 public function criterion_template($mode, $options, $elementname = '{NAME}', $criterion = null, $levelsstr = '{LEVELS}', $value = null) {
d22e9e32 60 // TODO MDL-31235 description format, remark format
ab156741
MG
61 if ($criterion === null || !is_array($criterion) || !array_key_exists('id', $criterion)) {
62 $criterion = array('id' => '{CRITERION-id}', 'description' => '{CRITERION-description}', 'sortorder' => '{CRITERION-sortorder}', 'class' => '{CRITERION-class}');
63 } else {
64 foreach (array('sortorder', 'description', 'class') as $key) {
65 // set missing array elements to empty strings to avoid warnings
66 if (!array_key_exists($key, $criterion)) {
67 $criterion[$key] = '';
68 }
69 }
70 }
3c2b3cb3 71 $criteriontemplate = html_writer::start_tag('tr', array('class' => 'criterion'. $criterion['class'], 'id' => '{NAME}-criteria-{CRITERION-id}'));
ab156741 72 if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FULL) {
3c2b3cb3 73 $criteriontemplate .= html_writer::start_tag('td', array('class' => 'controls'));
e22c8d2a 74 foreach (array('moveup', 'delete', 'movedown', 'duplicate') as $key) {
ab156741 75 $value = get_string('criterion'.$key, 'gradingform_rubric');
39c6f4b6 76 $button = html_writer::empty_tag('input', array('type' => 'submit', 'name' => '{NAME}[criteria][{CRITERION-id}]['.$key.']',
e9088e28 77 'id' => '{NAME}-criteria-{CRITERION-id}-'.$key, 'value' => $value));
3c2b3cb3 78 $criteriontemplate .= html_writer::tag('div', $button, array('class' => $key));
ab156741 79 }
e9088e28
JP
80 $criteriontemplate .= html_writer::empty_tag('input', array('type' => 'hidden',
81 'name' => '{NAME}[criteria][{CRITERION-id}][sortorder]',
82 'value' => $criterion['sortorder']));
3c2b3cb3 83 $criteriontemplate .= html_writer::end_tag('td'); // .controls
e9088e28
JP
84
85 // Criterion description text area.
86 $descriptiontextareaparams = array(
87 'name' => '{NAME}[criteria][{CRITERION-id}][description]',
88 'id' => '{NAME}-criteria-{CRITERION-id}-description',
89 'aria-label' => get_string('criterion', 'gradingform_rubric', ''),
90 'cols' => '10', 'rows' => '5'
91 );
92 $description = html_writer::tag('textarea', s($criterion['description']), $descriptiontextareaparams);
ab156741
MG
93 } else {
94 if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FROZEN) {
3c2b3cb3
MG
95 $criteriontemplate .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => '{NAME}[criteria][{CRITERION-id}][sortorder]', 'value' => $criterion['sortorder']));
96 $criteriontemplate .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => '{NAME}[criteria][{CRITERION-id}][description]', 'value' => $criterion['description']));
ab156741 97 }
b9b2968e 98 $description = s($criterion['description']);
ab156741 99 }
2ae7faf1
MG
100 $descriptionclass = 'description';
101 if (isset($criterion['error_description'])) {
102 $descriptionclass .= ' error';
103 }
e9088e28
JP
104
105 // Description cell params.
106 $descriptiontdparams = array(
107 'class' => $descriptionclass,
108 'id' => '{NAME}-criteria-{CRITERION-id}-description-cell'
109 );
110 if ($mode != gradingform_rubric_controller::DISPLAY_EDIT_FULL &&
111 $mode != gradingform_rubric_controller::DISPLAY_EDIT_FROZEN) {
112 // Set description's cell as tab-focusable.
113 $descriptiontdparams['tabindex'] = '0';
114 // Set label for the criterion cell.
115 $descriptiontdparams['aria-label'] = get_string('criterion', 'gradingform_rubric', s($criterion['description']));
116 }
117
118 // Description cell.
119 $criteriontemplate .= html_writer::tag('td', $description, $descriptiontdparams);
120
121 // Levels table.
122 $levelsrowparams = array('id' => '{NAME}-criteria-{CRITERION-id}-levels');
123 if ($mode != gradingform_rubric_controller::DISPLAY_EDIT_FULL) {
124 $levelsrowparams['role'] = 'radiogroup';
125 }
126 $levelsrow = html_writer::tag('tr', $levelsstr, $levelsrowparams);
127
128 $levelstableparams = array(
129 'id' => '{NAME}-criteria-{CRITERION-id}-levels-table',
130 'aria-label' => get_string('levelsgroup', 'gradingform_rubric')
131 );
132 $levelsstrtable = html_writer::tag('table', $levelsrow, $levelstableparams);
2ae7faf1
MG
133 $levelsclass = 'levels';
134 if (isset($criterion['error_levels'])) {
135 $levelsclass .= ' error';
136 }
3c2b3cb3 137 $criteriontemplate .= html_writer::tag('td', $levelsstrtable, array('class' => $levelsclass));
ab156741
MG
138 if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FULL) {
139 $value = get_string('criterionaddlevel', 'gradingform_rubric');
39c6f4b6 140 $button = html_writer::empty_tag('input', array('type' => 'submit', 'name' => '{NAME}[criteria][{CRITERION-id}][levels][addlevel]',
e9088e28 141 'id' => '{NAME}-criteria-{CRITERION-id}-levels-addlevel', 'value' => $value));
3c2b3cb3 142 $criteriontemplate .= html_writer::tag('td', $button, array('class' => 'addlevel'));
ab156741 143 }
39c6f4b6
MG
144 $displayremark = ($options['enableremarks'] && ($mode != gradingform_rubric_controller::DISPLAY_VIEW || $options['showremarksstudent']));
145 if ($displayremark) {
5060997b 146 $currentremark = '';
39c6f4b6
MG
147 if (isset($value['remark'])) {
148 $currentremark = $value['remark'];
149 }
e9088e28
JP
150
151 // Label for criterion remark.
152 $remarkinfo = new stdClass();
153 $remarkinfo->description = s($criterion['description']);
154 $remarkinfo->remark = $currentremark;
155 $remarklabeltext = get_string('criterionremark', 'gradingform_rubric', $remarkinfo);
156
39c6f4b6 157 if ($mode == gradingform_rubric_controller::DISPLAY_EVAL) {
e9088e28
JP
158 // HTML parameters for remarks text area.
159 $remarkparams = array(
160 'name' => '{NAME}[criteria][{CRITERION-id}][remark]',
161 'id' => '{NAME}-criteria-{CRITERION-id}-remark',
162 'cols' => '10', 'rows' => '5',
163 'aria-label' => $remarklabeltext
164 );
165 $input = html_writer::tag('textarea', s($currentremark), $remarkparams);
3c2b3cb3 166 $criteriontemplate .= html_writer::tag('td', $input, array('class' => 'remark'));
39c6f4b6 167 } else if ($mode == gradingform_rubric_controller::DISPLAY_EVAL_FROZEN) {
3c2b3cb3 168 $criteriontemplate .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => '{NAME}[criteria][{CRITERION-id}][remark]', 'value' => $currentremark));
39c6f4b6 169 }else if ($mode == gradingform_rubric_controller::DISPLAY_REVIEW || $mode == gradingform_rubric_controller::DISPLAY_VIEW) {
e9088e28
JP
170 // HTML parameters for remarks cell.
171 $remarkparams = array(
172 'class' => 'remark',
173 'tabindex' => '0',
174 'id' => '{NAME}-criteria-{CRITERION-id}-remark',
175 'aria-label' => $remarklabeltext
176 );
177 $criteriontemplate .= html_writer::tag('td', s($currentremark), $remarkparams);
39c6f4b6 178 }
5060997b 179 }
3c2b3cb3 180 $criteriontemplate .= html_writer::end_tag('tr'); // .criterion
ab156741 181
3c2b3cb3
MG
182 $criteriontemplate = str_replace('{NAME}', $elementname, $criteriontemplate);
183 $criteriontemplate = str_replace('{CRITERION-id}', $criterion['id'], $criteriontemplate);
184 return $criteriontemplate;
ab156741
MG
185 }
186
fc5adc3b
MG
187 /**
188 * This function returns html code for displaying one level of one criterion. Depending on $mode
189 * it may be the code to edit rubric, to preview the rubric, to evaluate somebody or to review the evaluation.
190 *
191 * This function may be called from display_rubric() to display the whole rubric, or it can be
192 * called by itself to return a template used by JavaScript to add new empty level to the
193 * criterion during the design of rubric.
194 * In this case it will use macros like {NAME}, {CRITERION-id}, {LEVEL-id}, etc.
195 *
196 * When overriding this function it is very important to remember that all elements of html
197 * form (in edit or evaluate mode) must have the name $elementname.
198 *
199 * Also JavaScript relies on the class names of elements and when developer changes them
200 * script might stop working.
201 *
d22e9e32
MG
202 * @param int $mode rubric display mode see {@link gradingform_rubric_controller}
203 * @param array $options display options for this rubric, defaults are: {@link gradingform_rubric_controller::get_default_options()}
fc5adc3b
MG
204 * @param string $elementname the name of the form element (in editor mode) or the prefix for div ids (in view mode)
205 * @param string|int $criterionid either id of the nesting criterion or a macro for template
206 * @param array|null $level level data, also in view mode it might also have property $level['checked'] whether this level is checked
207 * @return string
208 */
39c6f4b6 209 public function level_template($mode, $options, $elementname = '{NAME}', $criterionid = '{CRITERION-id}', $level = null) {
d22e9e32 210 // TODO MDL-31235 definition format
5060997b 211 if (!isset($level['id'])) {
ab156741
MG
212 $level = array('id' => '{LEVEL-id}', 'definition' => '{LEVEL-definition}', 'score' => '{LEVEL-score}', 'class' => '{LEVEL-class}', 'checked' => false);
213 } else {
e9088e28 214 foreach (array('score', 'definition', 'class', 'checked', 'index') as $key) {
ab156741
MG
215 // set missing array elements to empty strings to avoid warnings
216 if (!array_key_exists($key, $level)) {
217 $level[$key] = '';
218 }
219 }
220 }
221
e9088e28
JP
222 // Get level index.
223 $levelindex = isset($level['index']) ? $level['index'] : '{LEVEL-index}';
224
ab156741 225 // Template for one level within one criterion
e9088e28
JP
226 $tdattributes = array(
227 'id' => '{NAME}-criteria-{CRITERION-id}-levels-{LEVEL-id}',
228 'class' => 'level' . $level['class']
229 );
39c6f4b6
MG
230 if (isset($level['tdwidth'])) {
231 $tdattributes['width'] = round($level['tdwidth']).'%';
232 }
e9088e28
JP
233
234 $leveltemplate = html_writer::start_tag('div', array('class' => 'level-wrapper'));
ab156741 235 if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FULL) {
e9088e28
JP
236 $definitionparams = array(
237 'id' => '{NAME}-criteria-{CRITERION-id}-levels-{LEVEL-id}-definition',
238 'name' => '{NAME}[criteria][{CRITERION-id}][levels][{LEVEL-id}][definition]',
239 'aria-label' => get_string('leveldefinition', 'gradingform_rubric', $levelindex),
240 'cols' => '10', 'rows' => '4'
241 );
242 $definition = html_writer::tag('textarea', s($level['definition']), $definitionparams);
243
244 $scoreparams = array(
245 'type' => 'text',
246 'id' => '{NAME}[criteria][{CRITERION-id}][levels][{LEVEL-id}][score]',
247 'name' => '{NAME}[criteria][{CRITERION-id}][levels][{LEVEL-id}][score]',
248 'aria-label' => get_string('scoreinputforlevel', 'gradingform_rubric', $levelindex),
249 'size' => '3',
250 'value' => $level['score']
251 );
252 $score = html_writer::empty_tag('input', $scoreparams);
ab156741
MG
253 } else {
254 if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FROZEN) {
3c2b3cb3
MG
255 $leveltemplate .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => '{NAME}[criteria][{CRITERION-id}][levels][{LEVEL-id}][definition]', 'value' => $level['definition']));
256 $leveltemplate .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => '{NAME}[criteria][{CRITERION-id}][levels][{LEVEL-id}][score]', 'value' => $level['score']));
ab156741 257 }
b9b2968e 258 $definition = s($level['definition']);
ab156741
MG
259 $score = $level['score'];
260 }
261 if ($mode == gradingform_rubric_controller::DISPLAY_EVAL) {
e9088e28
JP
262 $levelradioparams = array(
263 'type' => 'radio',
264 'id' => '{NAME}-criteria-{CRITERION-id}-levels-{LEVEL-id}-definition',
265 'name' => '{NAME}[criteria][{CRITERION-id}][levelid]',
266 'value' => $level['id']
267 );
268 if ($level['checked']) {
269 $levelradioparams['checked'] = 'checked';
270 }
271 $input = html_writer::empty_tag('input', $levelradioparams);
272 $leveltemplate .= html_writer::div($input, 'radio');
ab156741
MG
273 }
274 if ($mode == gradingform_rubric_controller::DISPLAY_EVAL_FROZEN && $level['checked']) {
e9088e28
JP
275 $leveltemplate .= html_writer::empty_tag('input',
276 array(
277 'type' => 'hidden',
278 'name' => '{NAME}[criteria][{CRITERION-id}][levelid]',
279 'value' => $level['id']
280 )
281 );
ab156741 282 }
a19d1057 283 $score = html_writer::tag('span', $score, array('id' => '{NAME}-criteria-{CRITERION-id}-levels-{LEVEL-id}-score', 'class' => 'scorevalue'));
2ae7faf1
MG
284 $definitionclass = 'definition';
285 if (isset($level['error_definition'])) {
286 $definitionclass .= ' error';
287 }
e9088e28
JP
288
289 if ($mode != gradingform_rubric_controller::DISPLAY_EDIT_FULL &&
290 $mode != gradingform_rubric_controller::DISPLAY_EDIT_FROZEN) {
291
292 $tdattributes['tabindex'] = '0';
293 $levelinfo = new stdClass();
294 $levelinfo->definition = s($level['definition']);
295 $levelinfo->score = $level['score'];
296 $tdattributes['aria-label'] = get_string('level', 'gradingform_rubric', $levelinfo);
297
298 if ($mode != gradingform_rubric_controller::DISPLAY_PREVIEW &&
299 $mode != gradingform_rubric_controller::DISPLAY_PREVIEW_GRADED) {
300 // Add role of radio button to level cell if not in edit and preview mode.
301 $tdattributes['role'] = 'radio';
302 if ($level['checked']) {
303 $tdattributes['aria-checked'] = 'true';
304 } else {
305 $tdattributes['aria-checked'] = 'false';
306 }
307 }
308 }
309
310 $leveltemplateparams = array(
311 'id' => '{NAME}-criteria-{CRITERION-id}-levels-{LEVEL-id}-definition-container'
312 );
313 $leveltemplate .= html_writer::div($definition, $definitionclass, $leveltemplateparams);
39c6f4b6
MG
314 $displayscore = true;
315 if (!$options['showscoreteacher'] && in_array($mode, array(gradingform_rubric_controller::DISPLAY_EVAL, gradingform_rubric_controller::DISPLAY_EVAL_FROZEN, gradingform_rubric_controller::DISPLAY_REVIEW))) {
316 $displayscore = false;
317 }
577c8964 318 if (!$options['showscorestudent'] && in_array($mode, array(gradingform_rubric_controller::DISPLAY_VIEW, gradingform_rubric_controller::DISPLAY_PREVIEW_GRADED))) {
39c6f4b6
MG
319 $displayscore = false;
320 }
321 if ($displayscore) {
2ae7faf1
MG
322 $scoreclass = 'score';
323 if (isset($level['error_score'])) {
324 $scoreclass .= ' error';
325 }
3c2b3cb3 326 $leveltemplate .= html_writer::tag('div', get_string('scorepostfix', 'gradingform_rubric', $score), array('class' => $scoreclass));
39c6f4b6 327 }
ab156741 328 if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FULL) {
e9088e28
JP
329 $value = get_string('leveldelete', 'gradingform_rubric', $levelindex);
330 $buttonparams = array(
331 'type' => 'submit',
332 'name' => '{NAME}[criteria][{CRITERION-id}][levels][{LEVEL-id}][delete]',
333 'id' => '{NAME}-criteria-{CRITERION-id}-levels-{LEVEL-id}-delete',
334 'value' => $value
335 );
336 $button = html_writer::empty_tag('input', $buttonparams);
3c2b3cb3 337 $leveltemplate .= html_writer::tag('div', $button, array('class' => 'delete'));
ab156741 338 }
3c2b3cb3 339 $leveltemplate .= html_writer::end_tag('div'); // .level-wrapper
e9088e28
JP
340
341 $leveltemplate = html_writer::tag('td', $leveltemplate, $tdattributes); // The .level cell.
ab156741 342
3c2b3cb3
MG
343 $leveltemplate = str_replace('{NAME}', $elementname, $leveltemplate);
344 $leveltemplate = str_replace('{CRITERION-id}', $criterionid, $leveltemplate);
345 $leveltemplate = str_replace('{LEVEL-id}', $level['id'], $leveltemplate);
346 return $leveltemplate;
ab156741
MG
347 }
348
fc5adc3b
MG
349 /**
350 * This function returns html code for displaying rubric template (content before and after
351 * criteria list). Depending on $mode it may be the code to edit rubric, to preview the rubric,
352 * to evaluate somebody or to review the evaluation.
353 *
354 * This function is called from display_rubric() to display the whole rubric.
355 *
356 * When overriding this function it is very important to remember that all elements of html
357 * form (in edit or evaluate mode) must have the name $elementname.
358 *
359 * Also JavaScript relies on the class names of elements and when developer changes them
360 * script might stop working.
361 *
d22e9e32
MG
362 * @param int $mode rubric display mode see {@link gradingform_rubric_controller}
363 * @param array $options display options for this rubric, defaults are: {@link gradingform_rubric_controller::get_default_options()}
fc5adc3b 364 * @param string $elementname the name of the form element (in editor mode) or the prefix for div ids (in view mode)
3c2b3cb3 365 * @param string $criteriastr evaluated templates for this rubric's criteria
fc5adc3b
MG
366 * @return string
367 */
3c2b3cb3 368 protected function rubric_template($mode, $options, $elementname, $criteriastr) {
ab156741
MG
369 $classsuffix = ''; // CSS suffix for class of the main div. Depends on the mode
370 switch ($mode) {
371 case gradingform_rubric_controller::DISPLAY_EDIT_FULL:
372 $classsuffix = ' editor editable'; break;
373 case gradingform_rubric_controller::DISPLAY_EDIT_FROZEN:
374 $classsuffix = ' editor frozen'; break;
375 case gradingform_rubric_controller::DISPLAY_PREVIEW:
577c8964 376 case gradingform_rubric_controller::DISPLAY_PREVIEW_GRADED:
ab156741
MG
377 $classsuffix = ' editor preview'; break;
378 case gradingform_rubric_controller::DISPLAY_EVAL:
379 $classsuffix = ' evaluate editable'; break;
380 case gradingform_rubric_controller::DISPLAY_EVAL_FROZEN:
381 $classsuffix = ' evaluate frozen'; break;
382 case gradingform_rubric_controller::DISPLAY_REVIEW:
383 $classsuffix = ' review'; break;
39c6f4b6
MG
384 case gradingform_rubric_controller::DISPLAY_VIEW:
385 $classsuffix = ' view'; break;
ab156741
MG
386 }
387
3c2b3cb3 388 $rubrictemplate = html_writer::start_tag('div', array('id' => 'rubric-{NAME}', 'class' => 'clearfix gradingform_rubric'.$classsuffix));
e9088e28
JP
389
390 // Rubric table.
391 $rubrictableparams = array(
392 'class' => 'criteria',
393 'id' => '{NAME}-criteria',
394 'aria-label' => get_string('rubric', 'gradingform_rubric'));
395 $rubrictable = html_writer::tag('table', $criteriastr, $rubrictableparams);
396 $rubrictemplate .= $rubrictable;
ab156741
MG
397 if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FULL) {
398 $value = get_string('addcriterion', 'gradingform_rubric');
e9088e28
JP
399 $criteriainputparams = array(
400 'type' => 'submit',
401 'name' => '{NAME}[criteria][addcriterion]',
402 'id' => '{NAME}-criteria-addcriterion',
403 'value' => $value
404 );
405 $input = html_writer::empty_tag('input', $criteriainputparams);
cacf6925 406 $rubrictemplate .= html_writer::tag('div', $input, array('class' => 'addcriterion btn btn-secondary'));
ab156741 407 }
3c2b3cb3
MG
408 $rubrictemplate .= $this->rubric_edit_options($mode, $options);
409 $rubrictemplate .= html_writer::end_tag('div');
ab156741 410
3c2b3cb3 411 return str_replace('{NAME}', $elementname, $rubrictemplate);
ab156741
MG
412 }
413
3c2b3cb3
MG
414 /**
415 * Generates html template to view/edit the rubric options. Expression {NAME} is used in
416 * template for the form element name
417 *
d22e9e32
MG
418 * @param int $mode rubric display mode see {@link gradingform_rubric_controller}
419 * @param array $options display options for this rubric, defaults are: {@link gradingform_rubric_controller::get_default_options()}
3c2b3cb3
MG
420 * @return string
421 */
39c6f4b6
MG
422 protected function rubric_edit_options($mode, $options) {
423 if ($mode != gradingform_rubric_controller::DISPLAY_EDIT_FULL
424 && $mode != gradingform_rubric_controller::DISPLAY_EDIT_FROZEN
425 && $mode != gradingform_rubric_controller::DISPLAY_PREVIEW) {
577c8964 426 // Options are displayed only for people who can manage
39c6f4b6
MG
427 return;
428 }
429 $html = html_writer::start_tag('div', array('class' => 'options'));
430 $html .= html_writer::tag('div', get_string('rubricoptions', 'gradingform_rubric'), array('class' => 'optionsheading'));
431 $attrs = array('type' => 'hidden', 'name' => '{NAME}[options][optionsset]', 'value' => 1);
432 foreach ($options as $option => $value) {
433 $html .= html_writer::start_tag('div', array('class' => 'option '.$option));
434 $attrs = array('name' => '{NAME}[options]['.$option.']', 'id' => '{NAME}-options-'.$option);
435 switch ($option) {
436 case 'sortlevelsasc':
437 // Display option as dropdown
b7e3c249 438 $html .= html_writer::label(get_string($option, 'gradingform_rubric'), $attrs['id'], false);
39c6f4b6
MG
439 $value = (int)(!!$value); // make sure $value is either 0 or 1
440 if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FULL) {
441 $selectoptions = array(0 => get_string($option.'0', 'gradingform_rubric'), 1 => get_string($option.'1', 'gradingform_rubric'));
3c2b3cb3
MG
442 $valuestr = html_writer::select($selectoptions, $attrs['name'], $value, false, array('id' => $attrs['id']));
443 $html .= html_writer::tag('span', $valuestr, array('class' => 'value'));
39c6f4b6
MG
444 } else {
445 $html .= html_writer::tag('span', get_string($option.$value, 'gradingform_rubric'), array('class' => 'value'));
446 if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FROZEN) {
447 $html .= html_writer::empty_tag('input', $attrs + array('type' => 'hidden', 'value' => $value));
448 }
449 }
450 break;
451 default:
0136124e 452 if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FROZEN && $value) {
1ebda3eb
RT
453 // Id should be different then the actual input added later.
454 $attrs['id'] .= '_hidden';
0136124e
MG
455 $html .= html_writer::empty_tag('input', $attrs + array('type' => 'hidden', 'value' => $value));
456 }
39c6f4b6
MG
457 // Display option as checkbox
458 $attrs['type'] = 'checkbox';
459 $attrs['value'] = 1;
460 if ($value) {
461 $attrs['checked'] = 'checked';
462 }
0136124e 463 if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FROZEN || $mode == gradingform_rubric_controller::DISPLAY_PREVIEW) {
39c6f4b6
MG
464 $attrs['disabled'] = 'disabled';
465 unset($attrs['name']);
1ebda3eb
RT
466 // Id should be different then the actual input added later.
467 $attrs['id'] .= '_disabled';
39c6f4b6
MG
468 }
469 $html .= html_writer::empty_tag('input', $attrs);
470 $html .= html_writer::tag('label', get_string($option, 'gradingform_rubric'), array('for' => $attrs['id']));
471 break;
472 }
dfc261be
MG
473 if (get_string_manager()->string_exists($option.'_help', 'gradingform_rubric')) {
474 $html .= $this->help_icon($option, 'gradingform_rubric');
475 }
39c6f4b6
MG
476 $html .= html_writer::end_tag('div'); // .option
477 }
478 $html .= html_writer::end_tag('div'); // .options
479 return $html;
480 }
481
ab156741 482 /**
fc5adc3b
MG
483 * This function returns html code for displaying rubric. Depending on $mode it may be the code
484 * to edit rubric, to preview the rubric, to evaluate somebody or to review the evaluation.
485 *
486 * It is very unlikely that this function needs to be overriden by theme. It does not produce
487 * any html code, it just prepares data about rubric design and evaluation, adds the CSS
488 * class to elements and calls the functions level_template, criterion_template and
489 * rubric_template
ab156741 490 *
fc5adc3b 491 * @param array $criteria data about the rubric design
d22e9e32
MG
492 * @param array $options display options for this rubric, defaults are: {@link gradingform_rubric_controller::get_default_options()}
493 * @param int $mode rubric display mode, see {@link gradingform_rubric_controller}
fc5adc3b
MG
494 * @param string $elementname the name of the form element (in editor mode) or the prefix for div ids (in view mode)
495 * @param array $values evaluation result
ab156741
MG
496 * @return string
497 */
39c6f4b6 498 public function display_rubric($criteria, $options, $mode, $elementname = null, $values = null) {
3c2b3cb3 499 $criteriastr = '';
ab156741
MG
500 $cnt = 0;
501 foreach ($criteria as $id => $criterion) {
502 $criterion['class'] = $this->get_css_class_suffix($cnt++, sizeof($criteria) -1);
39c6f4b6 503 $criterion['id'] = $id;
3c2b3cb3 504 $levelsstr = '';
ab156741 505 $levelcnt = 0;
5060997b
MG
506 if (isset($values['criteria'][$id])) {
507 $criterionvalue = $values['criteria'][$id];
508 } else {
509 $criterionvalue = null;
510 }
e9088e28 511 $index = 1;
ab156741 512 foreach ($criterion['levels'] as $levelid => $level) {
39c6f4b6 513 $level['id'] = $levelid;
ab156741 514 $level['class'] = $this->get_css_class_suffix($levelcnt++, sizeof($criterion['levels']) -1);
5060997b 515 $level['checked'] = (isset($criterionvalue['levelid']) && ((int)$criterionvalue['levelid'] === $levelid));
39c6f4b6 516 if ($level['checked'] && ($mode == gradingform_rubric_controller::DISPLAY_EVAL_FROZEN || $mode == gradingform_rubric_controller::DISPLAY_REVIEW || $mode == gradingform_rubric_controller::DISPLAY_VIEW)) {
ab156741 517 $level['class'] .= ' checked';
fc5adc3b 518 //in mode DISPLAY_EVAL the class 'checked' will be added by JS if it is enabled. If JS is not enabled, the 'checked' class will only confuse
ab156741 519 }
188e840b
MG
520 if (isset($criterionvalue['savedlevelid']) && ((int)$criterionvalue['savedlevelid'] === $levelid)) {
521 $level['class'] .= ' currentchecked';
522 }
39c6f4b6 523 $level['tdwidth'] = 100/count($criterion['levels']);
e9088e28 524 $level['index'] = $index;
3c2b3cb3 525 $levelsstr .= $this->level_template($mode, $options, $elementname, $id, $level);
e9088e28 526 $index++;
ab156741 527 }
3c2b3cb3 528 $criteriastr .= $this->criterion_template($mode, $options, $elementname, $criterion, $levelsstr, $criterionvalue);
ab156741 529 }
3c2b3cb3 530 return $this->rubric_template($mode, $options, $elementname, $criteriastr);
ab156741
MG
531 }
532
533 /**
fc5adc3b 534 * Help function to return CSS class names for element (first/last/even/odd) with leading space
ab156741 535 *
3c2b3cb3
MG
536 * @param int $idx index of this element in the row/column
537 * @param int $maxidx maximum index of the element in the row/column
ab156741
MG
538 * @return string
539 */
3c2b3cb3 540 protected function get_css_class_suffix($idx, $maxidx) {
ab156741 541 $class = '';
3c2b3cb3 542 if ($idx == 0) {
ab156741
MG
543 $class .= ' first';
544 }
3c2b3cb3 545 if ($idx == $maxidx) {
ab156741
MG
546 $class .= ' last';
547 }
3c2b3cb3 548 if ($idx%2) {
ab156741
MG
549 $class .= ' odd';
550 } else {
551 $class .= ' even';
552 }
553 return $class;
554 }
36937f02
MG
555
556 /**
557 * Displays for the student the list of instances or default content if no instances found
558 *
559 * @param array $instances array of objects of type gradingform_rubric_instance
560 * @param string $defaultcontent default string that would be displayed without advanced grading
0136124e 561 * @param boolean $cangrade whether current user has capability to grade in this context
36937f02
MG
562 * @return string
563 */
0136124e 564 public function display_instances($instances, $defaultcontent, $cangrade) {
3c2b3cb3 565 $return = '';
36937f02 566 if (sizeof($instances)) {
3c2b3cb3 567 $return .= html_writer::start_tag('div', array('class' => 'advancedgrade'));
36937f02
MG
568 $idx = 0;
569 foreach ($instances as $instance) {
3c2b3cb3 570 $return .= $this->display_instance($instance, $idx++, $cangrade);
36937f02 571 }
3c2b3cb3 572 $return .= html_writer::end_tag('div');
36937f02 573 }
3c2b3cb3 574 return $return. $defaultcontent;
36937f02
MG
575 }
576
577 /**
578 * Displays one grading instance
579 *
580 * @param gradingform_rubric_instance $instance
d22e9e32
MG
581 * @param int $idx unique number of instance on page
582 * @param bool $cangrade whether current user has capability to grade in this context
36937f02 583 */
0136124e 584 public function display_instance(gradingform_rubric_instance $instance, $idx, $cangrade) {
36937f02 585 $criteria = $instance->get_controller()->get_definition()->rubric_criteria;
39c6f4b6 586 $options = $instance->get_controller()->get_options();
36937f02 587 $values = $instance->get_rubric_filling();
0136124e
MG
588 if ($cangrade) {
589 $mode = gradingform_rubric_controller::DISPLAY_REVIEW;
577c8964 590 $showdescription = $options['showdescriptionteacher'];
0136124e
MG
591 } else {
592 $mode = gradingform_rubric_controller::DISPLAY_VIEW;
577c8964 593 $showdescription = $options['showdescriptionstudent'];
0136124e 594 }
577c8964
MG
595 $output = '';
596 if ($showdescription) {
597 $output .= $this->box($instance->get_controller()->get_formatted_description(), 'gradingform_rubric-description');
598 }
599 $output .= $this->display_rubric($criteria, $options, $mode, 'rubric'.$idx, $values);
600 return $output;
0136124e
MG
601 }
602
d22e9e32
MG
603 /**
604 * Displays confirmation that students require re-grading
605 *
606 * @param string $elementname
607 * @param int $changelevel
608 * @param string $value
609 * @return string
610 */
0136124e 611 public function display_regrade_confirmation($elementname, $changelevel, $value) {
e9088e28 612 $html = html_writer::start_tag('div', array('class' => 'gradingform_rubric-regrade', 'role' => 'alert'));
0136124e 613 if ($changelevel<=2) {
29bea634 614 $html .= html_writer::label(get_string('regrademessage1', 'gradingform_rubric'), 'menu' . $elementname . 'regrade');
0136124e
MG
615 $selectoptions = array(
616 0 => get_string('regradeoption0', 'gradingform_rubric'),
617 1 => get_string('regradeoption1', 'gradingform_rubric')
618 );
619 $html .= html_writer::select($selectoptions, $elementname.'[regrade]', $value, false);
620 } else {
621 $html .= get_string('regrademessage5', 'gradingform_rubric');
622 $html .= html_writer::empty_tag('input', array('name' => $elementname.'[regrade]', 'value' => 1, 'type' => 'hidden'));
623 }
624 $html .= html_writer::end_tag('div');
625 return $html;
36937f02 626 }
a19d1057
MG
627
628 /**
629 * Generates and returns HTML code to display information box about how rubric score is converted to the grade
630 *
631 * @param array $scores
632 * @return string
633 */
634 public function display_rubric_mapping_explained($scores) {
635 $html = '';
636 if (!$scores) {
637 return $html;
638 }
3d91ad99
MG
639 if ($scores['minscore'] <> 0) {
640 $html .= $this->output->notification(get_string('zerolevelsabsent', 'gradingform_rubric'), 'error');
641 }
dfc261be 642 $html .= $this->output->notification(get_string('rubricmappingexplained', 'gradingform_rubric', (object)$scores), 'info');
a19d1057
MG
643 return $html;
644 }
c586d2bf 645}