Merge branch 'wip-MDL-53538-master' of git://github.com/abgreeve/moodle
[moodle.git] / mod / feedback / item / numeric / lib.php
CommitLineData
1adbd2c3 1<?php
9c5bc7a5
AG
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
01910dff 17defined('MOODLE_INTERNAL') OR die('not allowed');
c70ad9f7 18require_once($CFG->dirroot.'/mod/feedback/item/feedback_item_class.php');
19
20class feedback_item_numeric extends feedback_item_base {
9c5bc7a5
AG
21 protected $type = "numeric";
22 public $sep_dec, $sep_thous;
23 private $commonparams;
24 private $item_form;
25 private $item;
d4b1d58c 26
9c5bc7a5 27 public function init() {
fc9e2caa 28 $this->sep_dec = get_string('separator_decimal', 'feedback');
9c5bc7a5 29 if (substr($this->sep_dec, 0, 2) == '[[') {
fc9e2caa 30 $this->sep_dec = FEEDBACK_DECIMAL;
31 }
d4b1d58c 32
fc9e2caa 33 $this->sep_thous = get_string('separator_thousand', 'feedback');
9c5bc7a5 34 if (substr($this->sep_thous, 0, 2) == '[[') {
fc9e2caa 35 $this->sep_thous = FEEDBACK_THOUSAND;
d4b1d58c 36 }
c70ad9f7 37 }
d4b1d58c 38
9c5bc7a5 39 public function build_editform($item, $feedback, $cm) {
271fdd62 40 global $DB, $CFG;
6ee09cfe 41 require_once('numeric_form.php');
d4b1d58c 42
271fdd62
AG
43 //get the lastposition number of the feedback_items
44 $position = $item->position;
45 $lastposition = $DB->count_records('feedback_item', array('feedback'=>$feedback->id));
9c5bc7a5 46 if ($position == -1) {
271fdd62
AG
47 $i_formselect_last = $lastposition + 1;
48 $i_formselect_value = $lastposition + 1;
49 $item->position = $lastposition + 1;
9c5bc7a5 50 } else {
271fdd62
AG
51 $i_formselect_last = $lastposition;
52 $i_formselect_value = $item->position;
6ee09cfe 53 }
271fdd62 54 //the elements for position dropdownlist
9c5bc7a5
AG
55 $positionlist = array_slice(range(0, $i_formselect_last), 1, $i_formselect_last, true);
56
271fdd62 57 $item->presentation = empty($item->presentation) ? '' : $item->presentation;
9c5bc7a5
AG
58
59 $range_from_to = explode('|', $item->presentation);
60 if (isset($range_from_to[0]) AND is_numeric($range_from_to[0])) {
61 $range_from = str_replace(FEEDBACK_DECIMAL,
62 $this->sep_dec,
63 floatval($range_from_to[0]));
64 } else {
65 $range_from = '-';
66 }
67
68 if (isset($range_from_to[1]) AND is_numeric($range_from_to[1])) {
69 $range_to = str_replace(FEEDBACK_DECIMAL,
70 $this->sep_dec,
71 floatval($range_from_to[1]));
72 } else {
73 $range_to = '-';
74 }
75
271fdd62
AG
76 $item->rangefrom = $range_from;
77 $item->rangeto = $range_to;
78
73043833
AG
79 //all items for dependitem
80 $feedbackitems = feedback_get_depend_candidates_for_item($feedback, $item);
271fdd62 81 $commonparams = array('cmid'=>$cm->id,
9c5bc7a5 82 'id'=>isset($item->id) ? $item->id : null,
271fdd62 83 'typ'=>$item->typ,
73043833 84 'items'=>$feedbackitems,
271fdd62 85 'feedback'=>$feedback->id);
d4b1d58c 86
271fdd62 87 //build the form
9c5bc7a5
AG
88 $customdata = array('item' => $item,
89 'common' => $commonparams,
90 'positionlist' => $positionlist,
91 'position' => $position);
92
93 $this->item_form = new feedback_numeric_form('edit_item.php', $customdata);
271fdd62 94 }
d4b1d58c 95
271fdd62 96 //this function only can used after the call of build_editform()
9c5bc7a5 97 public function show_editform() {
271fdd62
AG
98 $this->item_form->display();
99 }
9c5bc7a5
AG
100
101 public function is_cancelled() {
271fdd62
AG
102 return $this->item_form->is_cancelled();
103 }
d4b1d58c 104
9c5bc7a5
AG
105 public function get_data() {
106 if ($this->item = $this->item_form->get_data()) {
271fdd62
AG
107 return true;
108 }
109 return false;
c70ad9f7 110 }
111
9c5bc7a5 112 public function save_item() {
271fdd62 113 global $DB;
9c5bc7a5
AG
114
115 if (!$item = $this->item_form->get_data()) {
271fdd62
AG
116 return false;
117 }
9c5bc7a5
AG
118
119 if (isset($item->clone_item) AND $item->clone_item) {
9e1aed53
AG
120 $item->id = ''; //to clone this item
121 $item->position++;
122 }
9c5bc7a5 123
45c2f92a 124 $item->hasvalue = $this->get_hasvalue();
9c5bc7a5 125 if (!$item->id) {
271fdd62 126 $item->id = $DB->insert_record('feedback_item', $item);
9c5bc7a5 127 } else {
271fdd62
AG
128 $DB->update_record('feedback_item', $item);
129 }
9c5bc7a5 130
271fdd62
AG
131 return $DB->get_record('feedback_item', array('id'=>$item->id));
132 }
133
134
c70ad9f7 135 //liefert eine Struktur ->name, ->data = array(mit Antworten)
9c5bc7a5 136 public function get_analysed($item, $groupid = false, $courseid = false) {
0085fff8 137 global $DB;
138
411fd747 139 $analysed = new stdClass();
c70ad9f7 140 $analysed->data = array();
141 $analysed->name = $item->name;
c70ad9f7 142 $values = feedback_get_group_values($item, $groupid, $courseid);
d4b1d58c 143
c70ad9f7 144 $avg = 0.0;
145 $counter = 0;
9c5bc7a5 146 if ($values) {
c70ad9f7 147 $data = array();
9c5bc7a5
AG
148 foreach ($values as $value) {
149 if (is_numeric($value->value)) {
c70ad9f7 150 $data[] = $value->value;
151 $avg += $value->value;
152 $counter++;
153 }
154 }
155 $avg = $counter > 0 ? $avg / $counter : 0;
156 $analysed->data = $data;
157 $analysed->avg = $avg;
158 }
159 return $analysed;
160 }
161
9c5bc7a5
AG
162 public function get_printval($item, $value) {
163 if (!isset($value->value)) {
164 return '';
165 }
d4b1d58c 166
c70ad9f7 167 return $value->value;
168 }
169
9c5bc7a5 170 public function print_analysed($item, $itemnr = '', $groupid = false, $courseid = false) {
d4b1d58c 171
c70ad9f7 172 $values = $this->get_analysed($item, $groupid, $courseid);
173
9c5bc7a5
AG
174 if (isset($values->data) AND is_array($values->data)) {
175 echo '<tr><th colspan="2" align="left">';
176 echo $itemnr.'&nbsp;('.$item->label.') '.$item->name;
177 echo '</th></tr>';
178
179 foreach ($values->data as $value) {
180 echo '<tr><td colspan="2" valign="top" align="left">';
181 echo '-&nbsp;&nbsp;'.number_format($value, 2, $this->sep_dec, $this->sep_thous);
182 echo '</td></tr>';
c70ad9f7 183 }
9c5bc7a5
AG
184
185 if (isset($values->avg)) {
fc9e2caa 186 $avg = number_format($values->avg, 2, $this->sep_dec, $this->sep_thous);
efc59167 187 } else {
fc9e2caa 188 $avg = number_format(0, 2, $this->sep_dec, $this->sep_thous);
efc59167 189 }
9c5bc7a5
AG
190 echo '<tr><td align="left" colspan="2"><b>';
191 echo get_string('average', 'feedback').': '.$avg;
192 echo '</b></td></tr>';
c70ad9f7 193 }
c70ad9f7 194 }
195
9c5bc7a5
AG
196 public function excelprint_item(&$worksheet, $row_offset,
197 $xls_formats, $item,
198 $groupid, $courseid = false) {
199
c70ad9f7 200 $analysed_item = $this->get_analysed($item, $groupid, $courseid);
201
9c5bc7a5
AG
202 $worksheet->write_string($row_offset, 0, $item->label, $xls_formats->head2);
203 $worksheet->write_string($row_offset, 1, $item->name, $xls_formats->head2);
c70ad9f7 204 $data = $analysed_item->data;
9c5bc7a5 205 if (is_array($data)) {
d4b1d58c 206
c70ad9f7 207 //mittelwert anzeigen
9c5bc7a5
AG
208 $worksheet->write_string($row_offset,
209 2,
210 get_string('average', 'feedback'),
211 $xls_formats->value_bold);
212
213 $worksheet->write_number($row_offset + 1,
214 2,
215 $analysed_item->avg,
216 $xls_formats->value_bold);
217 $row_offset++;
c70ad9f7 218 }
9c5bc7a5
AG
219 $row_offset++;
220 return $row_offset;
c70ad9f7 221 }
9c5bc7a5 222
5f17311f 223 /**
9d5fbd65
AG
224 * print the item at the edit-page of feedback
225 *
226 * @global object
227 * @param object $item
228 * @return void
229 */
9c5bc7a5 230 public function print_item_preview($item) {
73043833 231 global $OUTPUT, $DB;
9c5bc7a5 232
9d5fbd65 233 $align = right_to_left() ? 'right' : 'left';
cba01194
MM
234 $strrequiredmark = '<img class="req" title="'.get_string('requiredelement', 'form').'" alt="'.
235 get_string('requiredelement', 'form').'" src="'.$OUTPUT->pix_url('req') .'" />';
c70ad9f7 236
9d5fbd65 237 //get the range
9c5bc7a5
AG
238 $range_from_to = explode('|', $item->presentation);
239
9d5fbd65 240 //get the min-value
9c5bc7a5
AG
241 if (isset($range_from_to[0]) AND is_numeric($range_from_to[0])) {
242 $range_from = floatval($range_from_to[0]);
243 } else {
244 $range_from = 0;
245 }
246
9d5fbd65 247 //get the max-value
9c5bc7a5
AG
248 if (isset($range_from_to[1]) AND is_numeric($range_from_to[1])) {
249 $range_to = floatval($range_from_to[1]);
250 } else {
251 $range_to = 0;
252 }
253
cba01194 254 $requiredmark = ($item->required == 1) ? $strrequiredmark : '';
afdb1920 255 //print the question and label
bb4191ff 256 $inputname = $item->typ . '_' . $item->id;
afdb1920 257 echo '<div class="feedback_item_label_'.$align.'">';
690266bc 258 echo '<label for="'. $inputname .'">';
9c5bc7a5
AG
259 echo '('.$item->label.') ';
260 echo format_text($item->name . $requiredmark, true, false, false);
261 if ($item->dependitem) {
262 $params = array('id'=>$item->dependitem);
263 if ($dependitem = $DB->get_record('feedback_item', $params)) {
264 echo ' <span class="feedback_depend">';
265 echo '('.$dependitem->label.'-&gt;'.$item->dependvalue.')';
266 echo '</span>';
afdb1920 267 }
9c5bc7a5
AG
268 }
269 echo '<span class="feedback_item_numinfo">';
270 switch(true) {
271 case ($range_from === '-' AND is_numeric($range_to)):
272 echo ' ('.get_string('maximal', 'feedback').
273 ': '.str_replace(FEEDBACK_DECIMAL, $this->sep_dec, $range_to).')';
274 break;
275 case (is_numeric($range_from) AND $range_to === '-'):
276 echo ' ('.get_string('minimal', 'feedback').
277 ': '.str_replace(FEEDBACK_DECIMAL, $this->sep_dec, $range_from).')';
278 break;
279 case ($range_from === '-' AND $range_to === '-'):
280 break;
281 default:
282 echo ' ('.str_replace(FEEDBACK_DECIMAL, $this->sep_dec, $range_from).
283 ' - '.str_replace(FEEDBACK_DECIMAL, $this->sep_dec, $range_to).')';
284 break;
285 }
286 echo '</span>';
bb4191ff 287 echo '</label>';
afdb1920
AG
288 echo '</div>';
289
290 //print the presentation
291 echo '<div class="feedback_item_presentation_'.$align.'">';
292 echo '<span class="feedback_item_textfield">';
9c5bc7a5 293 echo '<input type="text" '.
690266bc
MM
294 'id="'.$inputname.'" '.
295 'name="'.$inputname.'" '.
9c5bc7a5
AG
296 'size="10" '.
297 'maxlength="10" '.
298 'value="" />';
299
afdb1920
AG
300 echo '</span>';
301 echo '</div>';
9d5fbd65 302 }
9c5bc7a5 303
5f17311f 304 /**
9d5fbd65
AG
305 * print the item at the complete-page of feedback
306 *
307 * @global object
308 * @param object $item
309 * @param string $value
310 * @param bool $highlightrequire
311 * @return void
312 */
9c5bc7a5 313 public function print_item_complete($item, $value = '', $highlightrequire = false) {
d4b1d58c 314 global $OUTPUT;
e372f4c7 315 $align = right_to_left() ? 'right' : 'left';
cba01194
MM
316 $strrequiredmark = '<img class="req" title="'.get_string('requiredelement', 'form').'" alt="'.
317 get_string('requiredelement', 'form').'" src="'.$OUTPUT->pix_url('req') .'" />';
d4b1d58c 318
c70ad9f7 319 //get the range
9c5bc7a5
AG
320 $range_from_to = explode('|', $item->presentation);
321
c70ad9f7 322 //get the min-value
9c5bc7a5
AG
323 if (isset($range_from_to[0]) AND is_numeric($range_from_to[0])) {
324 $range_from = floatval($range_from_to[0]);
325 } else {
326 $range_from = 0;
327 }
328
c70ad9f7 329 //get the max-value
9c5bc7a5
AG
330 if (isset($range_from_to[1]) AND is_numeric($range_from_to[1])) {
331 $range_to = floatval($range_from_to[1]);
332 } else {
333 $range_to = 0;
334 }
335
cba01194 336 $requiredmark = ($item->required == 1) ? $strrequiredmark : '';
9c5bc7a5 337
afdb1920 338 //print the question and label
bb4191ff 339 $inputname = $item->typ . '_' . $item->id;
cba01194 340 echo '<div class="feedback_item_label_'.$align.'">';
690266bc 341 echo '<label for="'. $inputname .'">';
9c5bc7a5
AG
342 echo format_text($item->name . $requiredmark, true, false, false);
343 echo '<span class="feedback_item_numinfo">';
344 switch(true) {
345 case ($range_from === '-' AND is_numeric($range_to)):
346 echo ' ('.get_string('maximal', 'feedback').
347 ': '.str_replace(FEEDBACK_DECIMAL, $this->sep_dec, $range_to).')';
348 break;
349 case (is_numeric($range_from) AND $range_to === '-'):
350 echo ' ('.get_string('minimal', 'feedback').
351 ': '.str_replace(FEEDBACK_DECIMAL, $this->sep_dec, $range_from).')';
352 break;
353 case ($range_from === '-' AND $range_to === '-'):
354 break;
355 default:
356 echo ' ('.str_replace(FEEDBACK_DECIMAL, $this->sep_dec, $range_from).
357 ' - '.str_replace(FEEDBACK_DECIMAL, $this->sep_dec, $range_to).')';
358 break;
359 }
360 echo '</span>';
cba01194
MM
361 if ($highlightrequire AND (!$this->check_value($value, $item))) {
362 echo '<br class="error"><span id="id_error_'.$inputname.'" class="error"> '.get_string('err_required', 'form').
363 '</span><br id="id_error_break_'.$inputname.'" class="error" >';
364 }
bb4191ff 365 echo '</label>';
afdb1920 366 echo '</div>';
9c5bc7a5 367
afdb1920 368 //print the presentation
cba01194 369 echo '<div class="feedback_item_presentation_'.$align.'">';
afdb1920 370 echo '<span class="feedback_item_textfield">';
9c5bc7a5 371 echo '<input type="text" '.
690266bc 372 'id="'.$inputname.'" '.
9c5bc7a5
AG
373 'name="'.$item->typ.'_'.$item->id.'" '.
374 'size="10" '.
375 'maxlength="10" '.
e7fc2ff4 376 'value="'.$value.'" />';
9c5bc7a5 377
afdb1920
AG
378 echo '</span>';
379 echo '</div>';
9d5fbd65
AG
380 }
381
5f17311f 382 /**
9d5fbd65
AG
383 * print the item at the complete-page of feedback
384 *
385 * @global object
386 * @param object $item
387 * @param string $value
388 * @return void
389 */
9c5bc7a5 390 public function print_item_show_value($item, $value = '') {
9d5fbd65
AG
391 global $OUTPUT;
392 $align = right_to_left() ? 'right' : 'left';
cba01194
MM
393 $strrequiredmark = '<img class="req" title="'.get_string('requiredelement', 'form').'" alt="'.
394 get_string('requiredelement', 'form').'" src="'.$OUTPUT->pix_url('req') .'" />';
9d5fbd65
AG
395
396 //get the range
9c5bc7a5 397 $range_from_to = explode('|', $item->presentation);
9d5fbd65 398 //get the min-value
9c5bc7a5
AG
399 if (isset($range_from_to[0]) AND is_numeric($range_from_to[0])) {
400 $range_from = floatval($range_from_to[0]);
401 } else {
402 $range_from = 0;
403 }
9d5fbd65 404 //get the max-value
9c5bc7a5
AG
405 if (isset($range_from_to[1]) AND is_numeric($range_from_to[1])) {
406 $range_to = floatval($range_from_to[1]);
407 } else {
408 $range_to = 0;
409 }
cba01194 410 $requiredmark = ($item->required == 1) ? $strrequiredmark : '';
9c5bc7a5 411
afdb1920
AG
412 //print the question and label
413 echo '<div class="feedback_item_label_'.$align.'">';
9c5bc7a5
AG
414 echo '('.$item->label.') ';
415 echo format_text($item->name . $requiredmark, true, false, false);
416 switch(true) {
417 case ($range_from === '-' AND is_numeric($range_to)):
418 echo ' ('.get_string('maximal', 'feedback').
419 ': '.str_replace(FEEDBACK_DECIMAL, $this->sep_dec, $range_to).')';
420 break;
421 case (is_numeric($range_from) AND $range_to === '-'):
422 echo ' ('.get_string('minimal', 'feedback').
423 ': '.str_replace(FEEDBACK_DECIMAL, $this->sep_dec, $range_from).')';
424 break;
425 case ($range_from === '-' AND $range_to === '-'):
426 break;
427 default:
428 echo ' ('.str_replace(FEEDBACK_DECIMAL, $this->sep_dec, $range_from).
429 ' - '.str_replace(FEEDBACK_DECIMAL, $this->sep_dec, $range_to).')';
430 break;
431 }
afdb1920 432 echo '</div>';
9c5bc7a5 433
afdb1920
AG
434 //print the presentation
435 echo '<div class="feedback_item_presentation_'.$align.'">';
9d5fbd65 436 echo $OUTPUT->box_start('generalbox boxalign'.$align);
9c5bc7a5
AG
437 if (is_numeric($value)) {
438 $str_num_value = number_format($value, 2, $this->sep_dec, $this->sep_thous);
439 } else {
440 $str_num_value = '&nbsp;';
441 }
442 echo $str_num_value;
9d5fbd65 443 echo $OUTPUT->box_end();
afdb1920 444 echo '</div>';
c70ad9f7 445 }
446
9c5bc7a5 447 public function check_value($value, $item) {
fc9e2caa 448 $value = str_replace($this->sep_dec, FEEDBACK_DECIMAL, $value);
c70ad9f7 449 //if the item is not required, so the check is true if no value is given
9c5bc7a5
AG
450 if ((!isset($value) OR $value == '') AND $item->required != 1) {
451 return true;
452 }
453 if (!is_numeric($value)) {
454 return false;
455 }
d4b1d58c 456
9c5bc7a5
AG
457 $range_from_to = explode('|', $item->presentation);
458 if (isset($range_from_to[0]) AND is_numeric($range_from_to[0])) {
459 $range_from = floatval($range_from_to[0]);
460 } else {
461 $range_from = '-';
462 }
463 if (isset($range_from_to[1]) AND is_numeric($range_from_to[1])) {
464 $range_to = floatval($range_from_to[1]);
465 } else {
466 $range_to = '-';
467 }
d4b1d58c 468
c70ad9f7 469 switch(true) {
fc9e2caa 470 case ($range_from === '-' AND is_numeric($range_to)):
9c5bc7a5
AG
471 if (floatval($value) <= $range_to) {
472 return true;
473 }
c70ad9f7 474 break;
fc9e2caa 475 case (is_numeric($range_from) AND $range_to === '-'):
9c5bc7a5
AG
476 if (floatval($value) >= $range_from) {
477 return true;
478 }
c70ad9f7 479 break;
fc9e2caa 480 case ($range_from === '-' AND $range_to === '-'):
c70ad9f7 481 return true;
482 break;
483 default:
9c5bc7a5
AG
484 if (floatval($value) >= $range_from AND floatval($value) <= $range_to) {
485 return true;
486 }
c70ad9f7 487 break;
488 }
d4b1d58c 489
c70ad9f7 490 return false;
491 }
492
9c5bc7a5 493 public function create_value($data) {
fc9e2caa 494 $data = str_replace($this->sep_dec, FEEDBACK_DECIMAL, $data);
d4b1d58c 495
9c5bc7a5 496 if (is_numeric($data)) {
fc9e2caa 497 $data = floatval($data);
9c5bc7a5 498 } else {
c70ad9f7 499 $data = '';
500 }
501 return $data;
502 }
503
73043833
AG
504 //compares the dbvalue with the dependvalue
505 //dbvalue is the number put in by the user
506 //dependvalue is the value that is compared
9c5bc7a5
AG
507 public function compare_value($item, $dbvalue, $dependvalue) {
508 if ($dbvalue == $dependvalue) {
73043833
AG
509 return true;
510 }
511 return false;
512 }
9c5bc7a5
AG
513
514 public function get_presentation($data) {
fc9e2caa 515 $num1 = str_replace($this->sep_dec, FEEDBACK_DECIMAL, $data->numericrangefrom);
9c5bc7a5 516 if (is_numeric($num1)) {
fc9e2caa 517 $num1 = floatval($num1);
9c5bc7a5 518 } else {
fc9e2caa 519 $num1 = '-';
520 }
d4b1d58c 521
fc9e2caa 522 $num2 = str_replace($this->sep_dec, FEEDBACK_DECIMAL, $data->numericrangeto);
9c5bc7a5 523 if (is_numeric($num2)) {
fc9e2caa 524 $num2 = floatval($num2);
9c5bc7a5 525 } else {
fc9e2caa 526 $num2 = '-';
527 }
d4b1d58c 528
9c5bc7a5 529 if ($num1 === '-' OR $num2 === '-') {
fc9e2caa 530 return $num1 . '|'. $num2;
531 }
d4b1d58c 532
9c5bc7a5 533 if ($num1 > $num2) {
fc9e2caa 534 return $num2 . '|'. $num1;
9c5bc7a5 535 } else {
d4b1d58c 536 return $num1 . '|'. $num2;
fc9e2caa 537 }
c70ad9f7 538 }
539
9c5bc7a5 540 public function get_hasvalue() {
c70ad9f7 541 return 1;
542 }
9c5bc7a5
AG
543
544 public function can_switch_require() {
6cc1599e
AG
545 return true;
546 }
5f17311f 547
e7fc2ff4
AG
548 public function value_type() {
549 return PARAM_FLOAT;
550 }
551
d2448b8b 552 public function clean_input_value($value) {
94848b07 553 $value = str_replace($this->sep_dec, FEEDBACK_DECIMAL, $value);
e7fc2ff4 554 if (!is_numeric($value)) {
94848b07
AG
555 if ($value == '') {
556 return null; //an empty string should be null
557 } else {
558 return clean_param($value, PARAM_TEXT); //we have to know the value if it is wrong
559 }
e7fc2ff4
AG
560 }
561 return clean_param($value, $this->value_type());
562 }
c70ad9f7 563}