MDL-31731 Grading form Marking Guide - fix for test 6.2, checkboxes not saving state...
[moodle.git] / grade / grading / form / guide / renderer.php
CommitLineData
77143217
DM
1<?php
2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16
17/**
18 * Contains the Guide grading form renderer in all of its glory
19 *
20 * @package gradingform_guide
21 * @copyright 2012 Dan Marsden <dan@danmarsden.com>
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24
25defined('MOODLE_INTERNAL') || die();
26
27/**
28 * Grading method plugin renderer
29 *
30 * @package gradingform_guide
31 * @copyright 2012 Dan Marsden <dan@danmarsden.com>
32 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
33 */
34class gradingform_guide_renderer extends plugin_renderer_base {
35
36 /**
37 * This function returns html code for displaying criterion. Depending on $mode it may be the
38 * code to edit guide, to preview the guide, to evaluate somebody or to review the evaluation.
39 *
40 * This function may be called from display_guide() to display the whole guide, or it can be
41 * called by itself to return a template used by JavaScript to add new empty criteria to the
42 * guide 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.
47 *
48 * Also JavaScript relies on the class names of elements and when developer changes them
49 * script might stop working.
50 *
51 * @param int $mode guide display mode, one of gradingform_guide_controller::DISPLAY_* {@link gradingform_guide_controller()}
52 * @param array $options An array of options.
53 * showmarkspercriterionstudents (bool) If true adds the current score to the display
54 * @param string $elementname the name of the form element (in editor mode) or the prefix for div ids (in view mode)
55 * @param array $criterion criterion data
56 * @param array $value (only in view mode) teacher's feedback on this criterion
57 * @param array $validationerrors An array containing validation errors to be shown
58 * @return string
59 */
60 public function criterion_template($mode, $options, $elementname = '{NAME}', $criterion = null, $value = null,
61 $validationerrors = null) {
62 if ($criterion === null || !is_array($criterion) || !array_key_exists('id', $criterion)) {
63 $criterion = array('id' => '{CRITERION-id}',
64 'description' => '{CRITERION-description}',
65 'sortorder' => '{CRITERION-sortorder}',
66 'class' => '{CRITERION-class}',
67 'descriptionmarkers' => '{CRITERION-descriptionmarkers}',
68 'shortname' => '{CRITERION-shortname}',
69 'maxscore' => '{CRITERION-maxscore}');
70 } else {
71 foreach (array('sortorder', 'description', 'class', 'shortname', 'descriptionmarkers', 'maxscore') as $key) {
72 // Set missing array elements to empty strings to avoid warnings.
73 if (!array_key_exists($key, $criterion)) {
74 $criterion[$key] = '';
75 }
76 }
77 }
78
79 $criteriontemplate = html_writer::start_tag('tr', array('class' => 'criterion'. $criterion['class'],
80 'id' => '{NAME}-criteria-{CRITERION-id}'));
81 $descriptionclass = 'description';
82 if ($mode == gradingform_guide_controller::DISPLAY_EDIT_FULL) {
83 $criteriontemplate .= html_writer::start_tag('td', array('class' => 'controls'));
84 foreach (array('moveup', 'delete', 'movedown') as $key) {
85 $value = get_string('criterion'.$key, 'gradingform_guide');
86 $button = html_writer::empty_tag('input', array('type' => 'submit',
87 'name' => '{NAME}[criteria][{CRITERION-id}]['.$key.']',
88 'id' => '{NAME}-criteria-{CRITERION-id}-'.$key, 'value' => $value, 'title' => $value, 'tabindex' => -1));
89 $criteriontemplate .= html_writer::tag('div', $button, array('class' => $key));
90 }
91 $criteriontemplate .= html_writer::end_tag('td'); // Controls.
92 $criteriontemplate .= html_writer::empty_tag('input', array('type' => 'hidden',
93 'name' => '{NAME}[criteria][{CRITERION-id}][sortorder]', 'value' => $criterion['sortorder']));
94
95 $shortname = html_writer::empty_tag('input', array('type'=> 'text',
96 'name' => '{NAME}[criteria][{CRITERION-id}][shortname]', 'value' => htmlspecialchars($criterion['shortname'])));
97 $shortname = html_writer::tag('div', $shortname, array('class'=>'criterionname'));
98 $description = html_writer::tag('textarea', htmlspecialchars($criterion['description']),
99 array('name' => '{NAME}[criteria][{CRITERION-id}][description]', 'cols' => '65', 'rows' => '5'));
100 $description = html_writer::tag('div', $description, array('class'=>'criteriondesc'));
101
102 $descriptionmarkers = html_writer::tag('textarea', htmlspecialchars($criterion['descriptionmarkers']),
103 array('name' => '{NAME}[criteria][{CRITERION-id}][descriptionmarkers]', 'cols' => '65', 'rows' => '5'));
104 $descriptionmarkers = html_writer::tag('div', $descriptionmarkers, array('class'=>'criteriondescmarkers'));
105
106 $maxscore = html_writer::empty_tag('input', array('type'=> 'text',
107 'name' => '{NAME}[criteria][{CRITERION-id}][maxscore]', 'size' => '3',
108 'value' => htmlspecialchars($criterion['maxscore'])));
109 $maxscore = html_writer::tag('div', $maxscore, array('class'=>'criterionmaxscore'));
110 } else {
111 if ($mode == gradingform_guide_controller::DISPLAY_EDIT_FROZEN) {
112 $criteriontemplate .= html_writer::empty_tag('input', array('type' => 'hidden',
113 'name' => '{NAME}[criteria][{CRITERION-id}][sortorder]', 'value' => $criterion['sortorder']));
114 $criteriontemplate .= html_writer::empty_tag('input', array('type' => 'hidden',
115 'name' => '{NAME}[criteria][{CRITERION-id}][shortname]', 'value' => $criterion['shortname']));
116 $criteriontemplate .= html_writer::empty_tag('input', array('type' => 'hidden',
117 'name' => '{NAME}[criteria][{CRITERION-id}][description]', 'value' => $criterion['description']));
118 $criteriontemplate .= html_writer::empty_tag('input', array('type' => 'hidden',
119 'name' => '{NAME}[criteria][{CRITERION-id}][descriptionmarkers]', 'value' => $criterion['descriptionmarkers']));
120 $criteriontemplate .= html_writer::empty_tag('input', array('type' => 'hidden',
121 'name' => '{NAME}[criteria][{CRITERION-id}][maxscore]', 'value' => $criterion['maxscore']));
122 } else if ($mode == gradingform_guide_controller::DISPLAY_EVAL ||
123 $mode == gradingform_guide_controller::DISPLAY_VIEW) {
124 $descriptionclass = 'descriptionreadonly';
125 }
126 $shortname = html_writer::tag('div', $criterion['shortname'],
127 array('class'=>'criterionshortname', 'name' => '{NAME}[criteria][{CRITERION-id}][shortname]'));
128 $descmarkerclass = '';
129 $descstudentclass = '';
130 if ($mode == gradingform_guide_controller::DISPLAY_EVAL) {
131 if (!get_user_preferences('gradingform_guide-showmarkerdesc', true)) {
132 $descmarkerclass = ' hide';
133 }
134 if (!get_user_preferences('gradingform_guide-showstudentdesc', true)) {
135 $descstudentclass = ' hide';
136 }
137 }
138 $description = html_writer::tag('div', $criterion['description'],
139 array('class'=>'criteriondescription'.$descstudentclass,
140 'name' => '{NAME}[criteria][{CRITERION-id}][descriptionmarkers]'));
141 $descriptionmarkers = html_writer::tag('div', $criterion['descriptionmarkers'],
142 array('class'=>'criteriondescriptionmarkers'.$descmarkerclass,
143 'name' => '{NAME}[criteria][{CRITERION-id}][descriptionmarkers]'));
144 $maxscore = html_writer::tag('div', $criterion['maxscore'],
145 array('class'=>'criteriondescriptionscore', 'name' => '{NAME}[criteria][{CRITERION-id}][maxscore]'));
146 }
147
148 if (isset($criterion['error_description'])) {
149 $descriptionclass .= ' error';
150 }
151
152 $title = html_writer::tag('label', get_string('criterion', 'gradingform_guide'),
153 array('for'=>'{NAME}[criteria][{CRITERION-id}][shortname]', 'class' => 'criterionnamelabel'));
154 $title .= $shortname;
155 if ($mode == gradingform_guide_controller::DISPLAY_EDIT_FULL ||
156 $mode == gradingform_guide_controller::DISPLAY_PREVIEW) {
157 $title .= html_writer::tag('label', get_string('descriptionstudents', 'gradingform_guide'),
158 array('for'=>'{NAME}[criteria][{CRITERION-id}][description]'));
159 $title .= $description;
160 $title .= html_writer::tag('label', get_string('descriptionmarkers', 'gradingform_guide'),
161 array('for'=>'{NAME}[criteria][{CRITERION-id}][descriptionmarkers]'));
162 $title .= $descriptionmarkers;
163 $title .= html_writer::tag('label', get_string('maxscore', 'gradingform_guide'),
164 array('for'=>'{NAME}[criteria][{CRITERION-id}][maxscore]'));
165 $title .= $maxscore;
166 } else if ($mode == gradingform_guide_controller::DISPLAY_PREVIEW_GRADED ||
167 $mode == gradingform_guide_controller::DISPLAY_VIEW) {
168 $title .= $description;
169 } else {
170 $title .= $description . $descriptionmarkers;
171 }
172 $criteriontemplate .= html_writer::tag('td', $title, array('class' => $descriptionclass,
173 'id' => '{NAME}-criteria-{CRITERION-id}-shortname'));
174
175 $currentremark = '';
176 $currentscore = '';
177 if (isset($value['remark'])) {
178 $currentremark = $value['remark'];
179 }
180 if (isset($value['score'])) {
181 $currentscore = $value['score'];
182 }
183 if ($mode == gradingform_guide_controller::DISPLAY_EVAL) {
184 $scoreclass = '';
185 if (!empty($validationerrors[$criterion['id']]['score'])) {
186 $scoreclass = 'error';
187 $currentscore = $validationerrors[$criterion['id']]['score']; // Show invalid score in form.
188 }
189 $input = html_writer::tag('textarea', htmlspecialchars($currentremark),
190 array('name' => '{NAME}[criteria][{CRITERION-id}][remark]', 'cols' => '65', 'rows' => '5',
191 'class' => 'markingguideremark'));
192 $criteriontemplate .= html_writer::tag('td', $input, array('class' => 'remark'));
193 $score = html_writer::tag('label', get_string('score', 'gradingform_guide'),
194 array('for'=>'{NAME}[criteria][{CRITERION-id}][score]', 'class' => $scoreclass));
195 $score .= html_writer::empty_tag('input', array('type'=> 'text',
196 'name' => '{NAME}[criteria][{CRITERION-id}][score]', 'class' => $scoreclass,
197 'size' => '3', 'value' => htmlspecialchars($currentscore)));
198 $score .= '/'.$maxscore;
199
200 $criteriontemplate .= html_writer::tag('td', $score, array('class' => 'score'));
201 } else if ($mode == gradingform_guide_controller::DISPLAY_EVAL_FROZEN) {
202 $criteriontemplate .= html_writer::empty_tag('input', array('type' => 'hidden',
203 'name' => '{NAME}[criteria][{CRITERION-id}][remark]', 'value' => $currentremark));
204 } else if ($mode == gradingform_guide_controller::DISPLAY_REVIEW ||
205 $mode == gradingform_guide_controller::DISPLAY_VIEW) {
206 $criteriontemplate .= html_writer::tag('td', $currentremark, array('class' => 'remark'));
207 if (!empty($options['showmarkspercriterionstudents'])) {
208 $criteriontemplate .= html_writer::tag('td', htmlspecialchars($currentscore). ' / '.$maxscore,
209 array('class' => 'score'));
210 }
211 }
212 $criteriontemplate .= html_writer::end_tag('tr'); // Criterion.
213
214 $criteriontemplate = str_replace('{NAME}', $elementname, $criteriontemplate);
215 $criteriontemplate = str_replace('{CRITERION-id}', $criterion['id'], $criteriontemplate);
216 return $criteriontemplate;
217 }
218
219 /**
220 * This function returns html code for displaying criterion. Depending on $mode it may be the
221 * code to edit guide, to preview the guide, to evaluate somebody or to review the evaluation.
222 *
223 * This function may be called from display_guide() to display the whole guide, or it can be
224 * called by itself to return a template used by JavaScript to add new empty criteria to the
225 * guide being designed.
226 * In this case it will use macros like {NAME}, {LEVELS}, {CRITERION-id}, etc.
227 *
228 * When overriding this function it is very important to remember that all elements of html
229 * form (in edit or evaluate mode) must have the name $elementname.
230 *
231 * Also JavaScript relies on the class names of elements and when developer changes them
232 * script might stop working.
233 *
234 * @param int $mode guide display mode, one of gradingform_guide_controller::DISPLAY_* {@link gradingform_guide_controller}
235 * @param string $elementname the name of the form element (in editor mode) or the prefix for div ids (in view mode)
236 * @param array $comment
237 * @return string
238 */
239 public function comment_template($mode, $elementname = '{NAME}', $comment = null) {
240 if ($comment === null || !is_array($comment) || !array_key_exists('id', $comment)) {
241 $comment = array('id' => '{COMMENT-id}',
242 'description' => '{COMMENT-description}',
243 'sortorder' => '{COMMENT-sortorder}',
244 'class' => '{COMMENT-class}');
245 } else {
246 foreach (array('sortorder', 'description', 'class') as $key) {
247 // Set missing array elements to empty strings to avoid warnings.
248 if (!array_key_exists($key, $comment)) {
249 $criterion[$key] = '';
250 }
251 }
252 }
253 $criteriontemplate = html_writer::start_tag('tr', array('class' => 'criterion'. $comment['class'],
254 'id' => '{NAME}-comments-{COMMENT-id}'));
255 if ($mode == gradingform_guide_controller::DISPLAY_EDIT_FULL) {
256 $criteriontemplate .= html_writer::start_tag('td', array('class' => 'controls'));
257 foreach (array('moveup', 'delete', 'movedown') as $key) {
258 $value = get_string('comments'.$key, 'gradingform_guide');
259 $button = html_writer::empty_tag('input', array('type' => 'submit',
260 'name' => '{NAME}[comments][{COMMENT-id}]['.$key.']', 'id' => '{NAME}-comments-{COMMENT-id}-'.$key,
261 'value' => $value, 'title' => $value, 'tabindex' => -1));
262 $criteriontemplate .= html_writer::tag('div', $button, array('class' => $key));
263 }
264 $criteriontemplate .= html_writer::end_tag('td'); // Controls.
265 $criteriontemplate .= html_writer::empty_tag('input', array('type' => 'hidden',
266 'name' => '{NAME}[comments][{COMMENT-id}][sortorder]', 'value' => $comment['sortorder']));
267 $description = html_writer::tag('textarea', htmlspecialchars($comment['description']),
268 array('name' => '{NAME}[comments][{COMMENT-id}][description]', 'cols' => '65', 'rows' => '5'));
269 $description = html_writer::tag('div', $description, array('class'=>'criteriondesc'));
270 } else {
271 if ($mode == gradingform_guide_controller::DISPLAY_EDIT_FROZEN) {
272 $criteriontemplate .= html_writer::empty_tag('input', array('type' => 'hidden',
273 'name' => '{NAME}[comments][{COMMENT-id}][sortorder]', 'value' => $comment['sortorder']));
274 $criteriontemplate .= html_writer::empty_tag('input', array('type' => 'hidden',
275 'name' => '{NAME}[comments][{COMMENT-id}][description]', 'value' => $comment['description']));
276 }
277 if ($mode == gradingform_guide_controller::DISPLAY_EVAL) {
278 $description = html_writer::tag('span', htmlspecialchars($comment['description']),
279 array('name' => '{NAME}[comments][{COMMENT-id}][description]',
280 'title' => get_string('clicktocopy', 'gradingform_guide'),
281 'id' => '{NAME}[comments][{COMMENT-id}]', 'class'=>'markingguidecomment'));
282 } else {
283 $description = $comment['description'];
284 }
285 }
286 $descriptionclass = 'description';
287 if (isset($comment['error_description'])) {
288 $descriptionclass .= ' error';
289 }
290 $criteriontemplate .= html_writer::tag('td', $description, array('class' => $descriptionclass,
291 'id' => '{NAME}-comments-{COMMENT-id}-description'));
292 $criteriontemplate .= html_writer::end_tag('tr'); // Criterion.
293
294 $criteriontemplate = str_replace('{NAME}', $elementname, $criteriontemplate);
295 $criteriontemplate = str_replace('{COMMENT-id}', $comment['id'], $criteriontemplate);
296 return $criteriontemplate;
297 }
298 /**
299 * This function returns html code for displaying guide template (content before and after
300 * criteria list). Depending on $mode it may be the code to edit guide, to preview the guide,
301 * to evaluate somebody or to review the evaluation.
302 *
303 * This function is called from display_guide() to display the whole guide.
304 *
305 * When overriding this function it is very important to remember that all elements of html
306 * form (in edit or evaluate mode) must have the name $elementname.
307 *
308 * Also JavaScript relies on the class names of elements and when developer changes them
309 * script might stop working.
310 *
311 * @param int $mode guide display mode, one of gradingform_guide_controller::DISPLAY_* {@link gradingform_guide_controller}
312 * @param array $options An array of options provided to {@link gradingform_guide_renderer::guide_edit_options()}
313 * @param string $elementname the name of the form element (in editor mode) or the prefix for div ids (in view mode)
314 * @param string $criteriastr evaluated templates for this guide's criteria
315 * @param string $commentstr
316 * @return string
317 */
318 protected function guide_template($mode, $options, $elementname, $criteriastr, $commentstr) {
319 $classsuffix = ''; // CSS suffix for class of the main div. Depends on the mode.
320 switch ($mode) {
321 case gradingform_guide_controller::DISPLAY_EDIT_FULL:
322 $classsuffix = ' editor editable';
323 break;
324 case gradingform_guide_controller::DISPLAY_EDIT_FROZEN:
325 $classsuffix = ' editor frozen';
326 break;
327 case gradingform_guide_controller::DISPLAY_PREVIEW:
328 case gradingform_guide_controller::DISPLAY_PREVIEW_GRADED:
329 $classsuffix = ' editor preview';
330 break;
331 case gradingform_guide_controller::DISPLAY_EVAL:
332 $classsuffix = ' evaluate editable';
333 break;
334 case gradingform_guide_controller::DISPLAY_EVAL_FROZEN:
335 $classsuffix = ' evaluate frozen';
336 break;
337 case gradingform_guide_controller::DISPLAY_REVIEW:
338 $classsuffix = ' review';
339 break;
340 case gradingform_guide_controller::DISPLAY_VIEW:
341 $classsuffix = ' view';
342 break;
343 }
344
345 $guidetemplate = html_writer::start_tag('div', array('id' => 'guide-{NAME}',
346 'class' => 'clearfix gradingform_guide'.$classsuffix));
347 $guidetemplate .= html_writer::tag('table', $criteriastr, array('class' => 'criteria', 'id' => '{NAME}-criteria'));
348 if ($mode == gradingform_guide_controller::DISPLAY_EDIT_FULL) {
349 $value = get_string('addcriterion', 'gradingform_guide');
350 $input = html_writer::empty_tag('input', array('type' => 'submit', 'name' => '{NAME}[criteria][addcriterion]',
351 'id' => '{NAME}-criteria-addcriterion', 'value' => $value, 'title' => $value));
352 $guidetemplate .= html_writer::tag('div', $input, array('class' => 'addcriterion'));
353 }
354
355 if (!empty($commentstr)) {
356 $guidetemplate .= html_writer::tag('label', get_string('comments', 'gradingform_guide'),
357 array('for' => '{NAME}-comments', 'class' => 'commentheader'));
358 $guidetemplate .= html_writer::tag('table', $commentstr, array('class' => 'comments', 'id' => '{NAME}-comments'));
359 }
360 if ($mode == gradingform_guide_controller::DISPLAY_EDIT_FULL) {
361 $value = get_string('addcomment', 'gradingform_guide');
362 $input = html_writer::empty_tag('input', array('type' => 'submit', 'name' => '{NAME}[comments][addcomment]',
363 'id' => '{NAME}-comments-addcomment', 'value' => $value, 'title' => $value));
364 $guidetemplate .= html_writer::tag('div', $input, array('class' => 'addcomment'));
365 }
366
367 $guidetemplate .= $this->guide_edit_options($mode, $options);
368 $guidetemplate .= html_writer::end_tag('div');
369
370 return str_replace('{NAME}', $elementname, $guidetemplate);
371 }
372
373 /**
374 * Generates html template to view/edit the guide options. Expression {NAME} is used in
375 * template for the form element name
376 *
377 * @param int $mode guide display mode, one of gradingform_guide_controller::DISPLAY_* {@link gradingform_guide_controller}
378 * @param array $options
379 * @return string
380 */
381 protected function guide_edit_options($mode, $options) {
382 if ($mode != gradingform_guide_controller::DISPLAY_EDIT_FULL
383 && $mode != gradingform_guide_controller::DISPLAY_EDIT_FROZEN
384 && $mode != gradingform_guide_controller::DISPLAY_PREVIEW) {
385 // Options are displayed only for people who can manage.
386 return;
387 }
388 $html = html_writer::start_tag('div', array('class' => 'options'));
389 $html .= html_writer::tag('div', get_string('guideoptions', 'gradingform_guide'), array('class' => 'optionsheading'));
390 $attrs = array('type' => 'hidden', 'name' => '{NAME}[options][optionsset]', 'value' => 1);
e529ec8c 391 $html .= html_writer::empty_tag('input', $attrs);
77143217
DM
392 foreach ($options as $option => $value) {
393 $html .= html_writer::start_tag('div', array('class' => 'option '.$option));
394 $attrs = array('name' => '{NAME}[options]['.$option.']', 'id' => '{NAME}-options-'.$option);
395 switch ($option) {
396 case 'sortlevelsasc':
397 // Display option as dropdown.
398 $html .= html_writer::tag('span', get_string($option, 'gradingform_guide'), array('class' => 'label'));
399 $value = (int)(!!$value); // Make sure $value is either 0 or 1.
400 if ($mode == gradingform_guide_controller::DISPLAY_EDIT_FULL) {
401 $selectoptions = array(0 => get_string($option.'0', 'gradingform_guide'),
402 1 => get_string($option.'1', 'gradingform_guide'));
403 $valuestr = html_writer::select($selectoptions, $attrs['name'], $value, false, array('id' => $attrs['id']));
404 $html .= html_writer::tag('span', $valuestr, array('class' => 'value'));
405 // TODO add here button 'Sort levels'.
406 } else {
407 $html .= html_writer::tag('span', get_string($option.$value, 'gradingform_guide'),
408 array('class' => 'value'));
409 if ($mode == gradingform_guide_controller::DISPLAY_EDIT_FROZEN) {
410 $html .= html_writer::empty_tag('input', $attrs + array('type' => 'hidden', 'value' => $value));
411 }
412 }
413 break;
414 default:
415 if ($mode == gradingform_guide_controller::DISPLAY_EDIT_FROZEN && $value) {
416 $html .= html_writer::empty_tag('input', $attrs + array('type' => 'hidden', 'value' => $value));
417 }
418 // Display option as checkbox.
419 $attrs['type'] = 'checkbox';
420 $attrs['value'] = 1;
421 if ($value) {
422 $attrs['checked'] = 'checked';
423 }
424 if ($mode == gradingform_guide_controller::DISPLAY_EDIT_FROZEN ||
425 $mode == gradingform_guide_controller::DISPLAY_PREVIEW) {
426 $attrs['disabled'] = 'disabled';
427 unset($attrs['name']);
428 }
429 $html .= html_writer::empty_tag('input', $attrs);
430 $html .= html_writer::tag('label', get_string($option, 'gradingform_guide'), array('for' => $attrs['id']));
431 break;
432 }
433 $html .= html_writer::end_tag('div'); // Option.
434 }
435 $html .= html_writer::end_tag('div'); // Options.
436 return $html;
437 }
438
439 /**
440 * This function returns html code for displaying guide. Depending on $mode it may be the code
441 * to edit guide, to preview the guide, to evaluate somebody or to review the evaluation.
442 *
443 * It is very unlikely that this function needs to be overriden by theme. It does not produce
444 * any html code, it just prepares data about guide design and evaluation, adds the CSS
445 * class to elements and calls the functions level_template, criterion_template and
446 * guide_template
447 *
448 * @param array $criteria data about the guide design
449 * @param array $comments
450 * @param array $options
451 * @param int $mode guide display mode, one of gradingform_guide_controller::DISPLAY_* {@link gradingform_guide_controller}
452 * @param string $elementname the name of the form element (in editor mode) or the prefix for div ids (in view mode)
453 * @param array $values evaluation result
454 * @param array $validationerrors
455 * @return string
456 */
457 public function display_guide($criteria, $comments, $options, $mode, $elementname = null, $values = null,
458 $validationerrors = null) {
459 $criteriastr = '';
460 $cnt = 0;
461 foreach ($criteria as $id => $criterion) {
462 $criterion['class'] = $this->get_css_class_suffix($cnt++, count($criteria) -1);
463 $criterion['id'] = $id;
464 if (isset($values['criteria'][$id])) {
465 $criterionvalue = $values['criteria'][$id];
466 } else {
467 $criterionvalue = null;
468 }
469 $criteriastr .= $this->criterion_template($mode, $options, $elementname, $criterion, $criterionvalue,
470 $validationerrors);
471 }
472 $cnt = 0;
473 $commentstr = '';
474 // Check if comments should be displayed.
475 if ($mode == gradingform_guide_controller::DISPLAY_EDIT_FULL ||
476 $mode == gradingform_guide_controller::DISPLAY_EDIT_FROZEN ||
477 $mode == gradingform_guide_controller::DISPLAY_PREVIEW ||
478 $mode == gradingform_guide_controller::DISPLAY_EVAL ||
479 $mode == gradingform_guide_controller::DISPLAY_EVAL_FROZEN) {
480
481 foreach ($comments as $id => $comment) {
482 $comment['id'] = $id;
483 $comment['class'] = $this->get_css_class_suffix($cnt++, count($comments) -1);
484 $commentstr .= $this->comment_template($mode, $elementname, $comment);
485 }
486 }
487 $output = $this->guide_template($mode, $options, $elementname, $criteriastr, $commentstr);
488 if ($mode == gradingform_guide_controller::DISPLAY_EVAL) {
489 $showdesc = get_user_preferences('gradingform_guide-showmarkerdesc', true);
490 $showdescstud = get_user_preferences('gradingform_guide-showstudentdesc', true);
491 $checked1 = array();
492 $checked2 = array();
493 $checked_s1 = array();
494 $checked_s2 = array();
495 $checked = array('checked' => 'checked');
496 if ($showdesc) {
497 $checked1 = $checked;
498 } else {
499 $checked2 = $checked;
500 }
501 if ($showdescstud) {
502 $checked_s1 = $checked;
503 } else {
504 $checked_s2 = $checked;
505 }
506
507 $radio = html_writer::tag('input', get_string('showmarkerdesc', 'gradingform_guide'), array('type' => 'radio',
508 'name' => 'showmarkerdesc',
509 'value' => "true")+$checked1);
510 $radio .= html_writer::tag('input', get_string('hidemarkerdesc', 'gradingform_guide'), array('type' => 'radio',
511 'name' => 'showmarkerdesc',
512 'value' => "false")+$checked2);
513 $output .= html_writer::tag('div', $radio, array('class' => 'showmarkerdesc'));
514
515 $radio = html_writer::tag('input', get_string('showstudentdesc', 'gradingform_guide'), array('type' => 'radio',
516 'name' => 'showstudentdesc',
517 'value' => "true")+$checked_s1);
518 $radio .= html_writer::tag('input', get_string('hidestudentdesc', 'gradingform_guide'), array('type' => 'radio',
519 'name' => 'showstudentdesc',
520 'value' => "false")+$checked_s2);
521 $output .= html_writer::tag('div', $radio, array('class' => 'showstudentdesc'));
522 }
523 return $output;
524 }
525
526 /**
527 * Help function to return CSS class names for element (first/last/even/odd) with leading space
528 *
529 * @param int $idx index of this element in the row/column
530 * @param int $maxidx maximum index of the element in the row/column
531 * @return string
532 */
533 protected function get_css_class_suffix($idx, $maxidx) {
534 $class = '';
535 if ($idx == 0) {
536 $class .= ' first';
537 }
538 if ($idx == $maxidx) {
539 $class .= ' last';
540 }
541 if ($idx % 2) {
542 $class .= ' odd';
543 } else {
544 $class .= ' even';
545 }
546 return $class;
547 }
548
549 /**
550 * Displays for the student the list of instances or default content if no instances found
551 *
552 * @param array $instances array of objects of type gradingform_guide_instance
553 * @param string $defaultcontent default string that would be displayed without advanced grading
554 * @param bool $cangrade whether current user has capability to grade in this context
555 * @return string
556 */
557 public function display_instances($instances, $defaultcontent, $cangrade) {
558 $return = '';
559 if (count($instances)) {
560 $return .= html_writer::start_tag('div', array('class' => 'advancedgrade'));
561 $idx = 0;
562 foreach ($instances as $instance) {
563 $return .= $this->display_instance($instance, $idx++, $cangrade);
564 }
565 $return .= html_writer::end_tag('div');
566 }
567 return $return. $defaultcontent;
568 }
569
570 /**
571 * Displays one grading instance
572 *
573 * @param gradingform_guide_instance $instance
574 * @param int $idx unique number of instance on page
575 * @param bool $cangrade whether current user has capability to grade in this context
576 */
577 public function display_instance(gradingform_guide_instance $instance, $idx, $cangrade) {
578 $criteria = $instance->get_controller()->get_definition()->guide_criteria;
579 $options = $instance->get_controller()->get_options();
580 $values = $instance->get_guide_filling();
581 if ($cangrade) {
582 $mode = gradingform_guide_controller::DISPLAY_REVIEW;
583 } else {
584 $mode = gradingform_guide_controller::DISPLAY_VIEW;
585 }
586
587 $output = $this->box($instance->get_controller()->get_formatted_description(), 'gradingform_guide-description').
588 $this->display_guide($criteria, array(), $options, $mode, 'guide'.$idx, $values);
589 return $output;
590 }
591
592
593 /**
594 * Displays a confirmation message after a regrade has occured
595 *
596 * @param string $elementname
597 * @param int $changelevel
598 * @param int $value The regrade option that was used
599 * @return string
600 */
601 public function display_regrade_confirmation($elementname, $changelevel, $value) {
602 $html = html_writer::start_tag('div', array('class' => 'gradingform_guide-regrade'));
603 if ($changelevel<=2) {
604 $html .= get_string('regrademessage1', 'gradingform_guide');
605 $selectoptions = array(
606 0 => get_string('regradeoption0', 'gradingform_guide'),
607 1 => get_string('regradeoption1', 'gradingform_guide')
608 );
609 $html .= html_writer::select($selectoptions, $elementname.'[regrade]', $value, false);
610 } else {
611 $html .= get_string('regrademessage5', 'gradingform_guide');
612 $html .= html_writer::empty_tag('input', array('name' => $elementname.'[regrade]', 'value' => 1, 'type' => 'hidden'));
613 }
614 $html .= html_writer::end_tag('div');
615 return $html;
616 }
617 /**
618 * Generates and returns HTML code to display information box about how guide score is converted to the grade
619 *
620 * @param array $scores
621 * @return string
622 */
623 public function display_guide_mapping_explained($scores) {
624 $html = '';
625 if (!$scores) {
626 return $html;
627 }
628 if (isset($scores['modulegrade']) && $scores['maxscore'] < $scores['modulegrade']) {
629 $html .= $this->box(html_writer::tag('div', get_string('guidemappingexplained', 'gradingform_guide', (object)$scores))
630 , 'generalbox gradingform_guide-error');
631 }
632
633 return $html;
634 }
635}