Form definitions can be removed now
[moodle.git] / grade / grading / form / rubric / renderer.php
CommitLineData
c586d2bf
MG
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/>.
17
18/**
19 * @package gradingform
20 * @subpackage rubric
21 * @copyright 2011 Marina Glancy
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24
25
26defined('MOODLE_INTERNAL') || die();
27
28/**
29 * Grading method plugin renderer
30 */
ab156741 31class gradingform_rubric_renderer {
c586d2bf 32
ab156741
MG
33 /**
34 *
35 * @param int $mode @see gradingform_rubric_controller
36 * @return string
37 */
38 public function criterion_template($mode, $elementname = '{NAME}', $criterion = null, $levels_str = '{LEVELS}') {
39 // TODO description format
40 if ($criterion === null || !is_array($criterion) || !array_key_exists('id', $criterion)) {
41 $criterion = array('id' => '{CRITERION-id}', 'description' => '{CRITERION-description}', 'sortorder' => '{CRITERION-sortorder}', 'class' => '{CRITERION-class}');
42 } else {
43 foreach (array('sortorder', 'description', 'class') as $key) {
44 // set missing array elements to empty strings to avoid warnings
45 if (!array_key_exists($key, $criterion)) {
46 $criterion[$key] = '';
47 }
48 }
49 }
50 $criterion_template = html_writer::start_tag('div', array('class' => 'clearfix criterion'. $criterion['class'], 'id' => '{NAME}-{CRITERION-id}'));
51 if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FULL) {
52 $criterion_template .= html_writer::start_tag('div', array('class' => 'controls'));
53 foreach (array('moveup', 'delete', 'movedown') as $key) {
54 $value = get_string('criterion'.$key, 'gradingform_rubric');
55 $button = html_writer::empty_tag('input', array('type' => 'submit', 'name' => '{NAME}[{CRITERION-id}]['.$key.']',
56 'id' => '{NAME}-{CRITERION-id}-'.$key, 'value' => $value, 'title' => $value));
57 $criterion_template .= html_writer::tag('div', $button, array('class' => $key));
58 }
59 $criterion_template .= html_writer::end_tag('div'); // .controls
60 $criterion_template .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => '{NAME}[{CRITERION-id}][sortorder]', 'value' => $criterion['sortorder']));
61 $description = html_writer::tag('textarea', htmlspecialchars($criterion['description']), array('name' => '{NAME}[{CRITERION-id}][description]', 'cols' => '10', 'rows' => '5'));
62 } else {
63 if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FROZEN) {
64 $criterion_template .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => '{NAME}[{CRITERION-id}][sortorder]', 'value' => $criterion['sortorder']));
65 $criterion_template .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => '{NAME}[{CRITERION-id}][description]', 'value' => $criterion['description']));
66 }
67 $description = $criterion['description'];
68 }
69 $criterion_template .= html_writer::tag('div', $description, array('class' => 'description', 'id' => '{NAME}-{CRITERION-id}-description'));
70 $criterion_template .= html_writer::tag('div', $levels_str, array('class' => 'clearfix levels', 'id' => '{NAME}-{CRITERION-id}-levels'));
71 if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FULL) {
72 $value = get_string('criterionaddlevel', 'gradingform_rubric');
73 $button = html_writer::empty_tag('input', array('type' => 'submit', 'name' => '{NAME}[{CRITERION-id}][levels][addlevel]',
74 'id' => '{NAME}-{CRITERION-id}-levels-addlevel', 'value' => $value, 'title' => $value)); //TODO '{NAME}-{CRITERION-id}-levels-addlevel
75 $criterion_template .= html_writer::tag('div', $button, array('class' => 'addlevel'));
76 }
77 $criterion_template .= html_writer::end_tag('div'); // .criterion
78
79 $criterion_template = str_replace('{NAME}', $elementname, $criterion_template);
80 $criterion_template = str_replace('{CRITERION-id}', $criterion['id'], $criterion_template);
81 return $criterion_template;
82 }
83
84 public function level_template($mode, $elementname = '{NAME}', $criterionid = '{CRITERION-id}', $level = null) {
85 // TODO definition format
86 if ($level === null || !is_array($level) || !array_key_exists('id', $level)) {
87 $level = array('id' => '{LEVEL-id}', 'definition' => '{LEVEL-definition}', 'score' => '{LEVEL-score}', 'class' => '{LEVEL-class}', 'checked' => false);
88 } else {
89 foreach (array('score', 'definition', 'class', 'checked') as $key) {
90 // set missing array elements to empty strings to avoid warnings
91 if (!array_key_exists($key, $level)) {
92 $level[$key] = '';
93 }
94 }
95 }
96
97 // Template for one level within one criterion
98 $level_template = html_writer::start_tag('div', array('id' => '{NAME}-{CRITERION-id}-levels-{LEVEL-id}', 'class' => 'clearfix level'. $level['class']));
99 if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FULL) {
100 $definition = html_writer::tag('textarea', htmlspecialchars($level['definition']), array('name' => '{NAME}[{CRITERION-id}][levels][{LEVEL-id}][definition]', 'cols' => '10', 'rows' => '4'));
101 $score = html_writer::empty_tag('input', array('type' => 'text', 'name' => '{NAME}[{CRITERION-id}][levels][{LEVEL-id}][score]', 'size' => '4', 'value' => $level['score']));
102 } else {
103 if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FROZEN) {
104 $level_template .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => '{NAME}[{CRITERION-id}][levels][{LEVEL-id}][definition]', 'value' => $level['definition']));
105 $level_template .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => '{NAME}[{CRITERION-id}][levels][{LEVEL-id}][score]', 'value' => $level['score']));
106 }
107 $definition = $level['definition'];
108 $score = $level['score'];
109 }
110 if ($mode == gradingform_rubric_controller::DISPLAY_EVAL) {
111 $input = html_writer::empty_tag('input', array('type' => 'radio', 'name' => '{NAME}[{CRITERION-id}]', 'value' => $level['id']) +
112 ($level['checked'] ? array('checked' => 'checked') : array()));
113 $level_template .= html_writer::tag('div', $input, array('class' => 'radio'));
114 }
115 if ($mode == gradingform_rubric_controller::DISPLAY_EVAL_FROZEN && $level['checked']) {
116 $html .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => '{NAME}[{CRITERION-id}]', 'value' => $level['id']));
117 }
118 $score = html_writer::tag('span', $score, array('id' => '{NAME}-{CRITERION-id}-levels-{LEVEL-id}-score'));
119 $level_template .= html_writer::tag('div', $definition, array('class' => 'definition', 'id' => '{NAME}-{CRITERION-id}-levels-{LEVEL-id}-definition'));
120 $level_template .= html_writer::tag('div', $score. get_string('scorepostfix', 'gradingform_rubric'), array('class' => 'score'));
121 if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FULL) {
122 $value = get_string('leveldelete', 'gradingform_rubric');
123 $button = html_writer::empty_tag('input', array('type' => 'submit', 'name' => '{NAME}[{CRITERION-id}][levels][{LEVEL-id}][delete]', 'id' => '{NAME}-{CRITERION-id}-levels-{LEVEL-id}-delete', 'value' => $value, 'title' => $value));
124 $level_template .= html_writer::tag('div', $button, array('class' => 'delete'));
125 }
126 $level_template .= html_writer::end_tag('div'); // .level
127
128 $level_template = str_replace('{NAME}', $elementname, $level_template);
129 $level_template = str_replace('{CRITERION-id}', $criterionid, $level_template);
130 $level_template = str_replace('{LEVEL-id}', $level['id'], $level_template);
131 return $level_template;
132 }
133
134 protected function rubric_template($mode, $elementname = '{NAME}', $criteria_str = '{CRITERIA}') {
135 $classsuffix = ''; // CSS suffix for class of the main div. Depends on the mode
136 switch ($mode) {
137 case gradingform_rubric_controller::DISPLAY_EDIT_FULL:
138 $classsuffix = ' editor editable'; break;
139 case gradingform_rubric_controller::DISPLAY_EDIT_FROZEN:
140 $classsuffix = ' editor frozen'; break;
141 case gradingform_rubric_controller::DISPLAY_PREVIEW:
142 $classsuffix = ' editor preview'; break;
143 case gradingform_rubric_controller::DISPLAY_EVAL:
144 $classsuffix = ' evaluate editable'; break;
145 case gradingform_rubric_controller::DISPLAY_EVAL_FROZEN:
146 $classsuffix = ' evaluate frozen'; break;
147 case gradingform_rubric_controller::DISPLAY_REVIEW:
148 $classsuffix = ' review'; break;
149 }
150
151 $rubric_template = html_writer::start_tag('div', array('id' => 'rubric-{NAME}', 'class' => 'clearfix form_rubric'.$classsuffix));
152 $rubric_template .= html_writer::tag('div', $criteria_str, array('class' => 'criteria', 'id' => '{NAME}-criteria'));
153 if ($mode == gradingform_rubric_controller::DISPLAY_EDIT_FULL) {
154 $value = get_string('addcriterion', 'gradingform_rubric');
155 $input = html_writer::empty_tag('input', array('type' => 'submit', 'name' => '{NAME}[addcriterion]', 'id' => '{NAME}-addcriterion', 'value' => $value, 'title' => $value));
156 $rubric_template .= html_writer::tag('div', $input, array('class' => 'addcriterion'));
157 }
158 $rubric_template .= html_writer::end_tag('div');
159
160 return str_replace('{NAME}', $elementname, $rubric_template);
161 }
162
163 /**
164 * Returns html code for displaying the rubric in the specified mode
165 *
166 * @param array $criteria
167 * @param int $mode
168 * @param string $elementname
169 * @param array $values
170 * @return string
171 */
172 public function display_rubric($criteria, $mode, $elementname = null, $values = null) {
173 $criteria_str = '';
174 $cnt = 0;
175 foreach ($criteria as $id => $criterion) {
176 $criterion['class'] = $this->get_css_class_suffix($cnt++, sizeof($criteria) -1);
177 $levels_str = '';
178 $levelcnt = 0;
179 foreach ($criterion['levels'] as $levelid => $level) {
180 $level['score'] = (float)$level['score']; // otherwise the display will look like 1.00000
181 $level['class'] = $this->get_css_class_suffix($levelcnt++, sizeof($criterion['levels']) -1);
182 $level['checked'] = (is_array($values) && (array_key_exists($id, $values) && ((int)$values[$id] === $levelid)));
183 if ($level['checked'] && ($mode == gradingform_rubric_controller::DISPLAY_EVAL_FROZEN || $mode == gradingform_rubric_controller::DISPLAY_REVIEW)) {
184 $level['class'] .= ' checked';
185 //in mode DISPLAY_EVAL the class 'checked' will be added by JS if it is enabled. If it is not enabled, the 'checked' class will only confuse
186 }
187 $levels_str .= $this->level_template($mode, $elementname, $id, $level);
188 }
189 $criteria_str .= $this->criterion_template($mode, $elementname, $criterion, $levels_str);
190 }
191 return $this->rubric_template($mode, $elementname, $criteria_str);
192 }
193
194 /**
195 * Help function to return CSS class names for element (first/last/even/odd)
196 *
197 * @param <type> $cnt
198 * @param <type> $maxcnt
199 * @return string
200 */
201 private function get_css_class_suffix($cnt, $maxcnt) {
202 $class = '';
203 if ($cnt == 0) {
204 $class .= ' first';
205 }
206 if ($cnt == $maxcnt) {
207 $class .= ' last';
208 }
209 if ($cnt%2) {
210 $class .= ' odd';
211 } else {
212 $class .= ' even';
213 }
214 return $class;
215 }
c586d2bf 216}