Commit | Line | Data |
---|---|---|
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 | defined('MOODLE_INTERNAL') || die(); | |
26 | ||
27 | require_once("HTML/QuickForm/input.php"); | |
28 | ||
29 | // register file-related rules | |
30 | if (class_exists('HTML_QuickForm')) { | |
31 | HTML_QuickForm::registerRule('rubriceditorcompleted', 'callback', '_ruleIsCompleted', 'MoodleQuickForm_rubriceditor'); | |
32 | } | |
33 | ||
34 | class MoodleQuickForm_rubriceditor extends HTML_QuickForm_input { | |
35 | public $_helpbutton = ''; | |
36 | ||
37 | function MoodleQuickForm_rubriceditor($elementName=null, $elementLabel=null, $attributes=null) { | |
38 | parent::HTML_QuickForm_input($elementName, $elementLabel, $attributes); | |
39 | } | |
40 | ||
41 | function getHelpButton() { | |
42 | return $this->_helpbutton; | |
43 | } | |
44 | ||
45 | function getElementTemplateType() { | |
46 | return 'default'; | |
47 | } | |
48 | ||
49 | function toHtml() { | |
50 | global $PAGE; | |
51 | $html = $this->_getTabs(); | |
52 | ||
53 | // Template for the whole rubric editor | |
54 | $classsuffix = $this->_flagFrozen ? 'frozen' : 'editable'; | |
55 | $rubric_template = html_writer::start_tag('div', array('id' => 'rubriceditor-{NAME}', 'class' => 'clearfix form_rubric editor '.$classsuffix)); | |
56 | $rubric_template .= html_writer::tag('div', '{CRITERIA}', array('class' => 'criteria', 'id' => '{NAME}-criteria')); | |
57 | if (!$this->_flagFrozen) { | |
58 | $rubric_template .= html_writer::empty_tag('input', array('type' => 'submit', 'name' => '{NAME}[addcriterion]', 'id' => '{NAME}-addcriterion', 'value' => get_string('addcriterion', 'gradingform_rubric'))); | |
59 | } | |
60 | $rubric_template .= html_writer::end_tag('div'); | |
61 | ||
62 | // Template for one criterion | |
63 | $criterion_template = html_writer::start_tag('div', array('class' => 'clearfix criterion{CRITERION-class}', 'id' => '{NAME}-{CRITERION-id}')); | |
64 | if (!$this->_flagFrozen) { | |
65 | $criterion_template .= html_writer::start_tag('div', array('class' => 'controls')); | |
66 | foreach (array('moveup', 'delete', 'movedown') as $key) { | |
67 | $button = html_writer::empty_tag('input', array('type' => 'submit', 'name' => '{NAME}[{CRITERION-id}]['.$key.']', | |
68 | 'id' => '{NAME}-{CRITERION-id}-'.$key, 'value' => get_string('criterion'.$key, 'gradingform_rubric'))); | |
69 | $criterion_template .= html_writer::tag('div', $button, array('class' => $key)); | |
70 | } | |
71 | $criterion_template .= html_writer::end_tag('div'); // .controls | |
72 | $criterion_template .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => '{NAME}[{CRITERION-id}][sortorder]', 'value' => '{CRITERION-sortorder}')); | |
73 | $description = html_writer::tag('textarea', '{CRITERION-description}', array('name' => '{NAME}[{CRITERION-id}][description]', 'cols' => '10', 'rows' => '5')); | |
74 | } else { | |
75 | if ($this->_persistantFreeze) { | |
76 | $criterion_template .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => '{NAME}[{CRITERION-id}][sortorder]', 'value' => '{CRITERION-sortorder}')); | |
77 | $criterion_template .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => '{NAME}[{CRITERION-id}][description]', 'value' => '{CRITERION-description}')); | |
78 | } | |
79 | $description = '{CRITERION-description}'; | |
80 | } | |
81 | $criterion_template .= html_writer::tag('div', $description, array('class' => 'description', 'id' => '{NAME}-{CRITERION-id}-description')); | |
82 | $criterion_template .= html_writer::tag('div', '{LEVELS}', array('class' => 'levels', 'id' => '{NAME}-{CRITERION-id}-levels')); | |
83 | if (!$this->_flagFrozen) { | |
84 | $button = html_writer::empty_tag('input', array('type' => 'submit', 'name' => '{NAME}[{CRITERION-id}][levels][addlevel]', | |
85 | 'id' => '{NAME}-{CRITERION-id}-addlevel', 'value' => get_string('criterionaddlevel', 'gradingform_rubric'))); //TODO '{NAME}-{CRITERION-id}-levels-addlevel | |
86 | $criterion_template .= html_writer::tag('div', $button, array('class' => 'addlevel')); | |
87 | } | |
88 | $criterion_template .= html_writer::end_tag('div'); // .criterion | |
89 | ||
90 | // Template for one level within one criterion | |
91 | $level_template = html_writer::start_tag('div', array('id' => '{NAME}-{CRITERION-id}-levels-{LEVEL-id}', 'class' => 'level{LEVEL-class}')); | |
92 | if (!$this->_flagFrozen) { | |
93 | $definition = html_writer::tag('textarea', '{LEVEL-definition}', array('name' => '{NAME}[{CRITERION-id}][levels][{LEVEL-id}][definition]', 'cols' => '10', 'rows' => '4')); | |
94 | $score = html_writer::empty_tag('input', array('type' => 'text', 'name' => '{NAME}[{CRITERION-id}][levels][{LEVEL-id}][score]', 'size' => '4', 'value' => '{LEVEL-score}')); | |
95 | } else { | |
96 | if ($this->_persistantFreeze) { | |
97 | $level_template .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => '{NAME}[{CRITERION-id}][levels][{LEVEL-id}][definition]', 'value' => '{LEVEL-definition}')); | |
98 | $level_template .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => '{NAME}[{CRITERION-id}][levels][{LEVEL-id}][score]', 'value' => '{LEVEL-score}')); | |
99 | } | |
100 | $definition = '{LEVEL-definition}'; | |
101 | $score = '{LEVEL-score}'; | |
102 | } | |
103 | $score = html_writer::tag('span', $score, array('id' => '{NAME}-{CRITERION-id}-levels-{LEVEL-id}-score')); | |
104 | $level_template .= html_writer::tag('div', $definition, array('class' => 'definition', 'id' => '{NAME}-{CRITERION-id}-levels-{LEVEL-id}-definition')); | |
105 | $level_template .= html_writer::tag('div', $score. get_string('scorepostfix', 'gradingform_rubric'), array('class' => 'score')); | |
106 | if (!$this->_flagFrozen) { | |
107 | $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' => get_string('leveldelete', 'gradingform_rubric'))); | |
108 | $level_template .= html_writer::tag('div', $button, array('class' => 'delete')); | |
109 | } | |
110 | $level_template .= html_writer::end_tag('div'); // .level | |
111 | ||
112 | $criterion_template = str_replace('{NAME}', $this->getName(), $criterion_template); | |
113 | $level_template = str_replace('{NAME}', $this->getName(), $level_template); | |
114 | $rubric_template = str_replace('{NAME}', $this->getName(), $rubric_template); | |
115 | ||
116 | if (!$this->_flagFrozen) { | |
117 | $module = array('name'=>'gradingform_rubriceditor', 'fullpath'=>'/grade/grading/form/rubric/js/rubriceditor.js', | |
118 | 'strings' => array(array('confirmdeletecriterion', 'gradingform_rubric'), array('confirmdeletelevel', 'gradingform_rubric'))); | |
119 | $PAGE->requires->js_init_call('M.gradingform_rubriceditor.init', array(array('name' => $this->getName(), 'criteriontemplate' => $criterion_template, 'leveltemplate' => $level_template)), true, $module); | |
120 | } | |
121 | $rubric_html = $rubric_template; | |
122 | $criteria = $this->prepare_non_js_data(); | |
123 | $cnt = 0; | |
124 | foreach ($criteria as $id => $criterion) { | |
125 | $criterion_html = $criterion_template; | |
126 | $levelcnt = 0; | |
127 | foreach ($criterion['levels'] as $levelid => $level) { | |
128 | $cell_html = $level_template; | |
129 | $cell_html = str_replace('{LEVEL-id}', $levelid, $cell_html); | |
130 | $cell_html = str_replace('{LEVEL-definition}', htmlspecialchars($level['definition']), $cell_html); | |
131 | $cell_html = str_replace('{LEVEL-score}', htmlspecialchars($level['score']), $cell_html); | |
132 | $cell_html = str_replace('{LEVEL-class}', $this->get_css_class_suffix($levelcnt++, sizeof($criterion['levels']) -1), $cell_html); | |
133 | $criterion_html = str_replace('{LEVELS}', $cell_html.'{LEVELS}', $criterion_html); | |
134 | } | |
135 | $criterion_html = str_replace('{LEVELS}', '', $criterion_html); | |
136 | $criterion_html = str_replace('{CRITERION-id}', $id, $criterion_html); | |
137 | $criterion_html = str_replace('{CRITERION-description}', htmlspecialchars($criterion['description']), $criterion_html); | |
138 | $criterion_html = str_replace('{CRITERION-sortorder}', htmlspecialchars($criterion['sortorder']), $criterion_html); | |
139 | $criterion_html = str_replace('{CRITERION-class}', $this->get_css_class_suffix($cnt++, sizeof($criteria) -1), $criterion_html); | |
140 | $rubric_html = str_replace('{CRITERIA}', $criterion_html.'{CRITERIA}', $rubric_html); | |
141 | } | |
142 | $rubric_html = str_replace('{CRITERIA}', '', $rubric_html); | |
143 | $html .= $rubric_html; | |
144 | ||
145 | return $html; | |
146 | } | |
147 | ||
148 | function get_css_class_suffix($cnt, $maxcnt) { | |
149 | $class = ''; | |
150 | if ($cnt == 0) { | |
151 | $class .= ' first'; | |
152 | } | |
153 | if ($cnt == $maxcnt) { | |
154 | $class .= ' last'; | |
155 | } | |
156 | if ($cnt%2) { | |
157 | $class .= ' odd'; | |
158 | } else { | |
159 | $class .= ' even'; | |
160 | } | |
161 | return $class; | |
162 | } | |
163 | ||
164 | function prepare_non_js_data() { | |
165 | $return = array(); | |
166 | $criteria = $this->getValue(); | |
167 | if (empty($criteria)) { | |
168 | $criteria = array(); | |
169 | } | |
170 | $lastaction = null; | |
171 | $lastid = null; | |
172 | foreach ($criteria as $id => $criterion) { | |
173 | if ($id == 'addcriterion') { | |
174 | $id = $this->get_next_id(array_keys($criteria)); | |
175 | $criterion = array('description' => ''); | |
176 | } | |
177 | $levels = array(); | |
178 | if (array_key_exists('levels', $criterion)) { | |
179 | foreach ($criterion['levels'] as $levelid => $level) { | |
180 | if ($levelid == 'addlevel') { | |
181 | $levelid = $this->get_next_id(array_keys($criterion['levels'])); | |
182 | $level = array( | |
183 | 'definition' => '', | |
184 | 'score' => 0, | |
185 | ); | |
186 | } | |
187 | if (!array_key_exists('delete', $level)) { | |
188 | $levels[$levelid] = $level; | |
189 | } | |
190 | } | |
191 | } | |
192 | $criterion['levels'] = $levels; | |
193 | if (array_key_exists('moveup', $criterion) || $lastaction == 'movedown') { | |
194 | unset($criterion['moveup']); | |
195 | if ($lastid !== null) { | |
196 | $lastcriterion = $return[$lastid]; | |
197 | unset($return[$lastid]); | |
198 | $return[$id] = $criterion; | |
199 | $return[$lastid] = $lastcriterion; | |
200 | } else { | |
201 | $return[$id] = $criterion; | |
202 | } | |
203 | $lastaction = null; | |
204 | $lastid = $id; | |
205 | } else if (array_key_exists('delete', $criterion)) { | |
206 | } else { | |
207 | if (array_key_exists('movedown', $criterion)) { | |
208 | unset($criterion['movedown']); | |
209 | $lastaction = 'movedown'; | |
210 | } | |
211 | $return[$id] = $criterion; | |
212 | $lastid = $id; | |
213 | } | |
214 | } | |
215 | $csortorder = 1; | |
216 | foreach (array_keys($return) as $id) { | |
217 | $return[$id]['sortorder'] = $csortorder++; | |
218 | } | |
219 | return $return; | |
220 | } | |
221 | ||
222 | function get_next_id($ids) { | |
223 | $maxid = 0; | |
224 | foreach ($ids as $id) { | |
225 | if (preg_match('/^NEWID(\d+)$/', $id, $matches) && ((int)$matches[1]) > $maxid) { | |
226 | $maxid = (int)$matches[1]; | |
227 | } | |
228 | } | |
229 | return 'NEWID'.($maxid+1); | |
230 | } | |
231 | ||
232 | function _ruleIsCompleted($elementValue) { | |
233 | //echo "_ruleIsCompleted"; | |
234 | if (is_array($elementValue)) { | |
235 | foreach ($elementValue as $criterionid => $criterion) { | |
236 | if ($criterionid == 'addcriterion') { | |
237 | return false; | |
238 | } | |
239 | if (array_key_exists('moveup', $criterion) || array_key_exists('movedown', $criterion) || array_key_exists('delete', $criterion)) { | |
240 | return false; | |
241 | } | |
242 | if (array_key_exists('levels', $criterion) && is_array($criterion['levels'])) { | |
243 | foreach ($criterion['levels'] as $levelid => $level) { | |
244 | if ($levelid == 'addlevel') { | |
245 | return false; | |
246 | } | |
247 | if (array_key_exists('delete', $level)) { | |
248 | return false; | |
249 | } | |
250 | } | |
251 | } | |
252 | } | |
253 | } | |
254 | //TODO check everything is filled | |
255 | //echo "<pre>";print_r($elementValue);echo "</pre>"; | |
256 | return true; | |
257 | } | |
258 | ||
259 | function onQuickFormEvent($event, $arg, &$caller) | |
260 | { | |
261 | $name = $this->getName(); | |
262 | if ($name && $caller->elementExists($name)) { | |
263 | $caller->addRule($name, '', 'rubriceditorcompleted'); | |
264 | } | |
265 | return parent::onQuickFormEvent($event, $arg, $caller); | |
266 | } | |
267 | ||
268 | } |