See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 401 and 402] [Versions 401 and 403]
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 * mod_feedback data generator. 19 * 20 * @package mod_feedback 21 * @category test 22 * @copyright 2013 Ankit Agarwal 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 defined('MOODLE_INTERNAL') || die(); 27 28 /** 29 * mod_feedback data generator class. 30 * 31 * @package mod_feedback 32 * @category test 33 * @copyright 2013 Ankit Agarwal 34 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 35 */ 36 class mod_feedback_generator extends testing_module_generator { 37 38 public function create_instance($record = null, array $options = null) { 39 global $CFG; 40 require_once($CFG->dirroot.'/mod/feedback/lib.php'); 41 $record = (object)(array)$record; 42 43 if (!isset($record->anonymous)) { 44 $record->anonymous = FEEDBACK_ANONYMOUS_YES; 45 } 46 if (!isset($record->email_notification)) { 47 $record->email_notification = 0; 48 } 49 if (!isset($record->multiple_submit)) { 50 $record->multiple_submit = 0; 51 } 52 if (!isset($record->autonumbering)) { 53 $record->autonumbering = 0; 54 } 55 if (!isset($record->site_after_submit)) { 56 $record->site_after_submit = ''; 57 } 58 if (!isset($record->page_after_submit)) { 59 $record->page_after_submit = 'This is page after submit'; 60 } 61 if (!isset($record->page_after_submitformat)) { 62 $record->page_after_submitformat = FORMAT_MOODLE; 63 } 64 if (!isset($record->publish_stats)) { 65 $record->publish_stats = 0; 66 } 67 if (!isset($record->timeopen)) { 68 $record->timeopen = 0; 69 } 70 if (!isset($record->timeclose)) { 71 $record->timeclose = 0; 72 } 73 if (!isset($record->timemodified)) { 74 $record->timemodified = time(); 75 } 76 if (!isset($record->completionsubmit)) { 77 $record->completionsubmit = 0; 78 } 79 80 // Hack to bypass draft processing of feedback_add_instance. 81 $record->page_after_submit_editor['itemid'] = false; 82 83 return parent::create_instance($record, (array)$options); 84 } 85 86 /** 87 * Create question. 88 * 89 * @param array $data Question data 90 * @return mixed Question instance 91 */ 92 public function create_question(array $data) { 93 global $DB; 94 95 $questiontype = $data['questiontype'] ?? 'textfield'; 96 $cm = get_coursemodule_from_id('feedback', $data['cmid']); 97 $feedback = $DB->get_record('feedback', ['id' => $cm->instance]); 98 99 unset($data['questiontype']); 100 unset($data['cmid']); 101 102 if (isset($data['values'])) { 103 $data['values'] = $this->format_item_values($questiontype, $data['values']); 104 } 105 106 return call_user_func([$this, "create_item_{$questiontype}"], $feedback, $data); 107 } 108 109 /** 110 * Create response. 111 * 112 * @param array $data Response data. 113 * @return stdClass feedback_completed response instance. 114 */ 115 public function create_response(array $data): stdClass { 116 global $DB; 117 118 $userid = $data['userid']; 119 $responsenumber = null; 120 $cm = get_coursemodule_from_id('feedback', $data['cmid']); 121 $feedback = $DB->get_record('feedback', ['id' => $cm->instance]); 122 $answers = []; 123 124 if (isset($data['responsenumber']) && trim($data['responsenumber']) !== '') { 125 $responsenumber = $data['responsenumber']; 126 } 127 128 if (isset($data['anonymous']) && trim($data['anonymous']) !== '') { 129 $anonymous = filter_var(trim($data['anonymous']), FILTER_VALIDATE_BOOLEAN); 130 $feedback->anonymous = $anonymous ? FEEDBACK_ANONYMOUS_YES : FEEDBACK_ANONYMOUS_NO; 131 } 132 133 unset($data['cmid']); 134 unset($data['userid']); 135 unset($data['anonymous']); 136 unset($data['responsenumber']); 137 138 foreach ($data as $question => $response) { 139 $item = $DB->get_record('feedback_item', ['name' => trim($question)], '*', MUST_EXIST); 140 141 $answers["{$item->typ}_{$item->id}"] = $this->get_item_response_value($item, $response); 142 } 143 144 $feedbackcompletion = new mod_feedback_completion( 145 $feedback, 146 $cm, 147 $cm->course, 148 false, 149 null, 150 $feedback->anonymous === FEEDBACK_ANONYMOUS_YES ? null : $userid, 151 $userid 152 ); 153 154 if (!$feedbackcompletion->can_complete()) { 155 throw new coding_exception("User {$userid} cannot complete this feedback activity."); 156 } 157 158 if (!$feedbackcompletion->is_open()) { 159 throw new coding_exception("This activity is not open."); 160 } 161 162 $feedbackcompletion->set_module_viewed(); 163 $feedbackcompletion->save_response_tmp((object) $answers); 164 $feedbackcompletion->save_response(); 165 $completed = $feedbackcompletion->get_completed(); 166 167 if (!is_null($responsenumber)) { 168 $DB->update_record('feedback_completed', [ 169 'id' => $completed->id, 170 'random_response' => $responsenumber, 171 ]); 172 } 173 174 return $completed; 175 } 176 177 /** 178 * Create info question item. 179 * 180 * @param object $feedback feedback record 181 * @param array $record (optional) to override default values 182 * @return int 183 */ 184 public function create_item_info($feedback, $record = array()) { 185 global $DB, $CFG; 186 187 require_once($CFG->dirroot.'/mod/feedback/lib.php'); 188 189 $itemobj = feedback_get_item_class('info'); 190 $position = $DB->count_records('feedback_item', array('feedback' => $feedback->id)) + 1; 191 192 $record = (array)$record + array( 193 'id' => 0, 194 'feedback' => $feedback->id, 195 'template' => 0, 196 'name' => 'Feedback question item ' . $position, 197 'label' => 'Feedback label ' . $position, 198 'presentation' => $itemobj::MODE_COURSE, 199 'typ' => 'info', 200 'hasvalue' => 0, 201 'position' => $position, 202 'required' => 0, 203 'dependitem' => 0, 204 'dependvalue' => '', 205 'options' => '', 206 ); 207 208 $itemobj->set_data((object) $record); 209 return $itemobj->save_item(); 210 } 211 212 /** 213 * Create label question item. 214 * 215 * @param object $feedback feedback record 216 * @param array $record (optional) to override default values 217 * @return int 218 */ 219 public function create_item_label($feedback, $record = array()) { 220 global $DB, $CFG; 221 222 require_once($CFG->dirroot.'/mod/feedback/lib.php'); 223 224 $itemobj = feedback_get_item_class('label'); 225 $position = $DB->count_records('feedback_item', array('feedback' => $feedback->id)) + 1; 226 227 $record = (array)$record + array( 228 'id' => 0, 229 'feedback' => $feedback->id, 230 'template' => 0, 231 'name' => 'label', 232 'label' => '', 233 'presentation' => '', 234 'typ' => 'label', 235 'hasvalue' => 0, 236 'position' => $position, 237 'required' => 0, 238 'dependitem' => 0, 239 'dependvalue' => '', 240 'options' => '', 241 ); 242 243 if (!isset($record['presentation_editor'])) { 244 $record['presentation_editor'] = array( 245 'text' => "The label $position text goes here", 246 'format' => FORMAT_HTML, 247 'itemid' => 0 248 ); 249 } 250 251 $itemobj->set_data((object) $record); 252 return $itemobj->save_item(); 253 } 254 255 /** 256 * Create multichoice question item. 257 * 258 * @param object $feedback feedback record 259 * @param array $record (optional) to override default values 260 * @return int 261 */ 262 public function create_item_multichoice($feedback, $record = array()) { 263 global $DB, $CFG; 264 265 require_once($CFG->dirroot.'/mod/feedback/lib.php'); 266 267 $itemobj = feedback_get_item_class('multichoice'); 268 $position = $DB->count_records('feedback_item', array('feedback' => $feedback->id)) + 1; 269 270 $record = (array)$record + array( 271 'id' => 0, 272 'feedback' => $feedback->id, 273 'template' => 0, 274 'name' => 'Feedback question item ' . $position, 275 'label' => 'Feedback label ' . $position, 276 'presentation' => '', 277 'typ' => 'multichoice', 278 'hasvalue' => 0, 279 'position' => $position, 280 'required' => 0, 281 'dependitem' => 0, 282 'dependvalue' => '', 283 'options' => '', 284 'subtype' => 'r', 285 'horizontal' => 0, 286 'hidenoselect' => 1, 287 'ignoreempty' => 0, 288 'values' => "a\nb\nc\nd\ne" 289 ); 290 291 $presentation = str_replace("\n", FEEDBACK_MULTICHOICE_LINE_SEP, trim($record['values'])); 292 293 if ($record['horizontal'] == 1 AND $record['subtype'] != 'd') { 294 $presentation .= FEEDBACK_MULTICHOICE_ADJUST_SEP.'1'; 295 } 296 $record['presentation'] = $record['subtype'].FEEDBACK_MULTICHOICE_TYPE_SEP.$presentation; 297 298 $itemobj->set_data((object) $record); 299 return $itemobj->save_item(); 300 } 301 302 /** 303 * Create multichoicerated question item. 304 * 305 * @param object $feedback feedback record 306 * @param array $record (optional) to override default values 307 * @return int 308 */ 309 public function create_item_multichoicerated($feedback, $record = array()) { 310 global $DB, $CFG; 311 312 require_once($CFG->dirroot.'/mod/feedback/lib.php'); 313 314 $itemobj = feedback_get_item_class('multichoicerated'); 315 $position = $DB->count_records('feedback_item', array('feedback' => $feedback->id)) + 1; 316 317 $record = (array)$record + array( 318 'id' => 0, 319 'feedback' => $feedback->id, 320 'template' => 0, 321 'name' => 'Feedback question item ' . $position, 322 'label' => 'Feedback label ' . $position, 323 'presentation' => '', 324 'typ' => 'multichoicerated', 325 'hasvalue' => 0, 326 'position' => $position, 327 'required' => 0, 328 'dependitem' => 0, 329 'dependvalue' => '', 330 'options' => '', 331 'subtype' => 'r', 332 'horizontal' => 0, 333 'hidenoselect' => 1, 334 'ignoreempty' => 0, 335 'values' => "0/a\n1/b\n2/c\n3/d\n4/e" 336 ); 337 338 $itemobj = new feedback_item_multichoicerated(); 339 $presentation = $itemobj->prepare_presentation_values_save(trim($record['values']), 340 FEEDBACK_MULTICHOICERATED_VALUE_SEP2, FEEDBACK_MULTICHOICERATED_VALUE_SEP); 341 342 if ($record['horizontal'] == 1 AND $record['subtype'] != 'd') { 343 $presentation .= FEEDBACK_MULTICHOICERATED_ADJUST_SEP.'1'; 344 } 345 $record['presentation'] = $record['subtype'].FEEDBACK_MULTICHOICERATED_TYPE_SEP.$presentation; 346 347 $itemobj->set_data((object) $record); 348 return $itemobj->save_item(); 349 } 350 351 /** 352 * Create numeric question item. 353 * 354 * @param object $feedback feedback record 355 * @param array $record (optional) to override default values 356 * @return int 357 */ 358 public function create_item_numeric($feedback, $record = array()) { 359 global $DB, $CFG; 360 361 require_once($CFG->dirroot.'/mod/feedback/lib.php'); 362 363 $itemobj = feedback_get_item_class('numeric'); 364 $position = $DB->count_records('feedback_item', array('feedback' => $feedback->id)) + 1; 365 366 $record = (array)$record + array( 367 'id' => 0, 368 'feedback' => $feedback->id, 369 'template' => 0, 370 'name' => 'Feedback question item ' . $position, 371 'label' => 'Feedback label ' . $position, 372 'presentation' => '', 373 'typ' => 'numeric', 374 'hasvalue' => 0, 375 'position' => $position, 376 'required' => 0, 377 'dependitem' => 0, 378 'dependvalue' => '', 379 'options' => '', 380 'rangefrom' => '-', 381 'rangeto' => '-', 382 ); 383 384 if ($record['rangefrom'] === '-' OR $record['rangeto'] === '-') { 385 $record['presentation'] = $record['rangefrom'] . '|'. $record['rangeto']; 386 } else if ($record['rangefrom'] > $record['rangeto']) { 387 $record['presentation'] = $record['rangeto'] . '|'. $record['rangefrom']; 388 } else { 389 $record['presentation'] = $record['rangefrom'] . '|'. $record['rangeto']; 390 } 391 392 $itemobj->set_data((object) $record); 393 return $itemobj->save_item(); 394 } 395 396 /** 397 * Create textarea question item. 398 * 399 * @param object $feedback feedback record 400 * @param array $record (optional) to override default values 401 * @return int 402 */ 403 public function create_item_textarea($feedback, $record = array()) { 404 global $DB, $CFG; 405 406 require_once($CFG->dirroot.'/mod/feedback/lib.php'); 407 408 $itemobj = feedback_get_item_class('textarea'); 409 $position = $DB->count_records('feedback_item', array('feedback' => $feedback->id)) + 1; 410 411 $record = (array)$record + array( 412 'id' => 0, 413 'feedback' => $feedback->id, 414 'template' => 0, 415 'name' => 'Feedback question item ' . $position, 416 'label' => 'Feedback label ' . $position, 417 'presentation' => '', 418 'typ' => 'textarea', 419 'hasvalue' => 0, 420 'position' => $position, 421 'required' => 0, 422 'dependitem' => 0, 423 'dependvalue' => '', 424 'options' => '', 425 'itemwidth' => '40', 426 'itemheight' => '20', 427 ); 428 429 $record['presentation'] = $record['itemwidth'] . '|'. $record['itemheight']; 430 431 $itemobj->set_data((object) $record); 432 return $itemobj->save_item(); 433 } 434 435 /** 436 * Create textfield question item. 437 * 438 * @param object $feedback feedback record 439 * @param array $record (optional) to override default values 440 * @return int 441 */ 442 public function create_item_textfield($feedback, $record = array()) { 443 global $DB, $CFG; 444 445 require_once($CFG->dirroot.'/mod/feedback/lib.php'); 446 447 $itemobj = feedback_get_item_class('textfield'); 448 $position = $DB->count_records('feedback_item', array('feedback' => $feedback->id)) + 1; 449 450 $record = (array)$record + array( 451 'id' => 0, 452 'feedback' => $feedback->id, 453 'template' => 0, 454 'name' => 'Feedback question item ' . $position, 455 'label' => 'Feedback label ' . $position, 456 'presentation' => '', 457 'typ' => 'textfield', 458 'hasvalue' => 0, 459 'position' => $position, 460 'required' => 0, 461 'dependitem' => 0, 462 'dependvalue' => '', 463 'options' => '', 464 'itemsize' => '20', 465 'itemmaxlength' => '30', 466 ); 467 468 $record['presentation'] = $record['itemsize'] . '|'. $record['itemmaxlength']; 469 470 $itemobj->set_data((object) $record); 471 return $itemobj->save_item(); 472 } 473 474 /** 475 * Create pagebreak. 476 * 477 * @param object $feedback feedback record 478 * @return mixed false if there already is a pagebreak on last position or the id of the pagebreak-item 479 */ 480 public function create_item_pagebreak($feedback) { 481 global $CFG; 482 require_once($CFG->dirroot.'/mod/feedback/lib.php'); 483 484 return feedback_create_pagebreak($feedback->id); 485 } 486 487 /** 488 * Format feedback item values. 489 * 490 * This method will replace newline characters with the proper line separator for each question type. 491 * 492 * @param string $questiontype Question types 493 * @param string $values Values 494 * @return string Formatted values 495 */ 496 protected function format_item_values(string $questiontype, string $values): string { 497 global $CFG; 498 499 if (!file_exists($CFG->dirroot.'/mod/feedback/item/'.$questiontype.'/lib.php')) { 500 throw new coding_exception("Question type '$questiontype' not found"); 501 } 502 503 require_once($CFG->dirroot.'/mod/feedback/item/'.$questiontype.'/lib.php'); 504 505 $questiontype = strtoupper($questiontype); 506 507 if (defined("FEEDBACK_{$questiontype}_LINE_SEP")) { 508 return implode(constant("FEEDBACK_{$questiontype}_LINE_SEP"), explode('\n', $values)); 509 } 510 511 return $values; 512 } 513 514 /** 515 * Given a response to a feedback item, return its corresponding value. 516 * 517 * @param mixed $record Item record 518 * @param string $response Response name 519 * @return int|string Response value 520 */ 521 protected function get_item_response_value($record, string $response) { 522 if (strpos($record->typ, 'multichoice') === 0) { 523 $item = feedback_get_item_class($record->typ); 524 525 return $this->get_choice_item_response_value($item, $record, $response); 526 } 527 528 return $response; 529 } 530 531 /** 532 * Given a response to a feedback choice item, return its corresponding value. 533 * 534 * @param feedback_item_base $item Feedback item 535 * @param mixed $record Item record 536 * @param string $response Response 537 * @param int $offset Choice to start looking from 538 * @return int Response choice index 539 */ 540 protected function get_choice_item_response_value(feedback_item_base $item, $record, string $response, int $offset = 1): int { 541 $printval = $item->get_printval($record, (object) ['value' => $offset]); 542 543 if (empty($printval)) { 544 throw new coding_exception("Value '$offset' not found"); 545 } 546 547 if ($printval === $response) { 548 return $offset; 549 } 550 551 return $this->get_choice_item_response_value($item, $record, $response, $offset + 1); 552 } 553 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body