[ Index ] |
PHP Cross Reference of moodle-2.8 |
[Summary view] [Print] [Text view]
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 * Library of functions and constants for module feedback 19 * includes the main-part of feedback-functions 20 * 21 * @package mod_feedback 22 * @copyright Andreas Grabs 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 /** Include eventslib.php */ 27 require_once($CFG->libdir.'/eventslib.php'); 28 /** Include calendar/lib.php */ 29 require_once($CFG->dirroot.'/calendar/lib.php'); 30 // Include forms lib. 31 require_once($CFG->libdir.'/formslib.php'); 32 33 define('FEEDBACK_ANONYMOUS_YES', 1); 34 define('FEEDBACK_ANONYMOUS_NO', 2); 35 define('FEEDBACK_MIN_ANONYMOUS_COUNT_IN_GROUP', 2); 36 define('FEEDBACK_DECIMAL', '.'); 37 define('FEEDBACK_THOUSAND', ','); 38 define('FEEDBACK_RESETFORM_RESET', 'feedback_reset_data_'); 39 define('FEEDBACK_RESETFORM_DROP', 'feedback_drop_feedback_'); 40 define('FEEDBACK_MAX_PIX_LENGTH', '400'); //max. Breite des grafischen Balkens in der Auswertung 41 define('FEEDBACK_DEFAULT_PAGE_COUNT', 20); 42 43 /** 44 * Returns all other caps used in module. 45 * 46 * @return array 47 */ 48 function feedback_get_extra_capabilities() { 49 return array('moodle/site:accessallgroups'); 50 } 51 52 /** 53 * @uses FEATURE_GROUPS 54 * @uses FEATURE_GROUPINGS 55 * @uses FEATURE_MOD_INTRO 56 * @uses FEATURE_COMPLETION_TRACKS_VIEWS 57 * @uses FEATURE_GRADE_HAS_GRADE 58 * @uses FEATURE_GRADE_OUTCOMES 59 * @param string $feature FEATURE_xx constant for requested feature 60 * @return mixed True if module supports feature, null if doesn't know 61 */ 62 function feedback_supports($feature) { 63 switch($feature) { 64 case FEATURE_GROUPS: return true; 65 case FEATURE_GROUPINGS: return true; 66 case FEATURE_MOD_INTRO: return true; 67 case FEATURE_COMPLETION_TRACKS_VIEWS: return true; 68 case FEATURE_COMPLETION_HAS_RULES: return true; 69 case FEATURE_GRADE_HAS_GRADE: return false; 70 case FEATURE_GRADE_OUTCOMES: return false; 71 case FEATURE_BACKUP_MOODLE2: return true; 72 case FEATURE_SHOW_DESCRIPTION: return true; 73 74 default: return null; 75 } 76 } 77 78 /** 79 * this will create a new instance and return the id number 80 * of the new instance. 81 * 82 * @global object 83 * @param object $feedback the object given by mod_feedback_mod_form 84 * @return int 85 */ 86 function feedback_add_instance($feedback) { 87 global $DB; 88 89 $feedback->timemodified = time(); 90 $feedback->id = ''; 91 92 if (empty($feedback->site_after_submit)) { 93 $feedback->site_after_submit = ''; 94 } 95 96 //saving the feedback in db 97 $feedbackid = $DB->insert_record("feedback", $feedback); 98 99 $feedback->id = $feedbackid; 100 101 feedback_set_events($feedback); 102 103 if (!isset($feedback->coursemodule)) { 104 $cm = get_coursemodule_from_id('feedback', $feedback->id); 105 $feedback->coursemodule = $cm->id; 106 } 107 $context = context_module::instance($feedback->coursemodule); 108 109 $editoroptions = feedback_get_editor_options(); 110 111 // process the custom wysiwyg editor in page_after_submit 112 if ($draftitemid = $feedback->page_after_submit_editor['itemid']) { 113 $feedback->page_after_submit = file_save_draft_area_files($draftitemid, $context->id, 114 'mod_feedback', 'page_after_submit', 115 0, $editoroptions, 116 $feedback->page_after_submit_editor['text']); 117 118 $feedback->page_after_submitformat = $feedback->page_after_submit_editor['format']; 119 } 120 $DB->update_record('feedback', $feedback); 121 122 return $feedbackid; 123 } 124 125 /** 126 * this will update a given instance 127 * 128 * @global object 129 * @param object $feedback the object given by mod_feedback_mod_form 130 * @return boolean 131 */ 132 function feedback_update_instance($feedback) { 133 global $DB; 134 135 $feedback->timemodified = time(); 136 $feedback->id = $feedback->instance; 137 138 if (empty($feedback->site_after_submit)) { 139 $feedback->site_after_submit = ''; 140 } 141 142 //save the feedback into the db 143 $DB->update_record("feedback", $feedback); 144 145 //create or update the new events 146 feedback_set_events($feedback); 147 148 $context = context_module::instance($feedback->coursemodule); 149 150 $editoroptions = feedback_get_editor_options(); 151 152 // process the custom wysiwyg editor in page_after_submit 153 if ($draftitemid = $feedback->page_after_submit_editor['itemid']) { 154 $feedback->page_after_submit = file_save_draft_area_files($draftitemid, $context->id, 155 'mod_feedback', 'page_after_submit', 156 0, $editoroptions, 157 $feedback->page_after_submit_editor['text']); 158 159 $feedback->page_after_submitformat = $feedback->page_after_submit_editor['format']; 160 } 161 $DB->update_record('feedback', $feedback); 162 163 return true; 164 } 165 166 /** 167 * Serves the files included in feedback items like label. Implements needed access control ;-) 168 * 169 * There are two situations in general where the files will be sent. 170 * 1) filearea = item, 2) filearea = template 171 * 172 * @package mod_feedback 173 * @category files 174 * @param stdClass $course course object 175 * @param stdClass $cm course module object 176 * @param stdClass $context context object 177 * @param string $filearea file area 178 * @param array $args extra arguments 179 * @param bool $forcedownload whether or not force download 180 * @param array $options additional options affecting the file serving 181 * @return bool false if file not found, does not return if found - justsend the file 182 */ 183 function feedback_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) { 184 global $CFG, $DB; 185 186 if ($filearea === 'item' or $filearea === 'template') { 187 $itemid = (int)array_shift($args); 188 //get the item what includes the file 189 if (!$item = $DB->get_record('feedback_item', array('id'=>$itemid))) { 190 return false; 191 } 192 $feedbackid = $item->feedback; 193 $templateid = $item->template; 194 } 195 196 if ($filearea === 'page_after_submit' or $filearea === 'item') { 197 if (! $feedback = $DB->get_record("feedback", array("id"=>$cm->instance))) { 198 return false; 199 } 200 201 $feedbackid = $feedback->id; 202 203 //if the filearea is "item" so we check the permissions like view/complete the feedback 204 $canload = false; 205 //first check whether the user has the complete capability 206 if (has_capability('mod/feedback:complete', $context)) { 207 $canload = true; 208 } 209 210 //now we check whether the user has the view capability 211 if (has_capability('mod/feedback:view', $context)) { 212 $canload = true; 213 } 214 215 //if the feedback is on frontpage and anonymous and the fullanonymous is allowed 216 //so the file can be loaded too. 217 if (isset($CFG->feedback_allowfullanonymous) 218 AND $CFG->feedback_allowfullanonymous 219 AND $course->id == SITEID 220 AND $feedback->anonymous == FEEDBACK_ANONYMOUS_YES ) { 221 $canload = true; 222 } 223 224 if (!$canload) { 225 return false; 226 } 227 } else if ($filearea === 'template') { //now we check files in templates 228 if (!$template = $DB->get_record('feedback_template', array('id'=>$templateid))) { 229 return false; 230 } 231 232 //if the file is not public so the capability edititems has to be there 233 if (!$template->ispublic) { 234 if (!has_capability('mod/feedback:edititems', $context)) { 235 return false; 236 } 237 } else { //on public templates, at least the user has to be logged in 238 if (!isloggedin()) { 239 return false; 240 } 241 } 242 } else { 243 return false; 244 } 245 246 if ($context->contextlevel == CONTEXT_MODULE) { 247 if ($filearea !== 'item' and $filearea !== 'page_after_submit') { 248 return false; 249 } 250 } 251 252 if ($context->contextlevel == CONTEXT_COURSE || $context->contextlevel == CONTEXT_SYSTEM) { 253 if ($filearea !== 'template') { 254 return false; 255 } 256 } 257 258 $relativepath = implode('/', $args); 259 if ($filearea === 'page_after_submit') { 260 $fullpath = "/{$context->id}/mod_feedback/$filearea/$relativepath"; 261 } else { 262 $fullpath = "/{$context->id}/mod_feedback/$filearea/{$item->id}/$relativepath"; 263 } 264 265 $fs = get_file_storage(); 266 267 if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) { 268 return false; 269 } 270 271 // finally send the file 272 send_stored_file($file, 0, 0, true, $options); // download MUST be forced - security! 273 274 return false; 275 } 276 277 /** 278 * this will delete a given instance. 279 * all referenced data also will be deleted 280 * 281 * @global object 282 * @param int $id the instanceid of feedback 283 * @return boolean 284 */ 285 function feedback_delete_instance($id) { 286 global $DB; 287 288 //get all referenced items 289 $feedbackitems = $DB->get_records('feedback_item', array('feedback'=>$id)); 290 291 //deleting all referenced items and values 292 if (is_array($feedbackitems)) { 293 foreach ($feedbackitems as $feedbackitem) { 294 $DB->delete_records("feedback_value", array("item"=>$feedbackitem->id)); 295 $DB->delete_records("feedback_valuetmp", array("item"=>$feedbackitem->id)); 296 } 297 if ($delitems = $DB->get_records("feedback_item", array("feedback"=>$id))) { 298 foreach ($delitems as $delitem) { 299 feedback_delete_item($delitem->id, false); 300 } 301 } 302 } 303 304 //deleting the referenced tracking data 305 $DB->delete_records('feedback_tracking', array('feedback'=>$id)); 306 307 //deleting the completeds 308 $DB->delete_records("feedback_completed", array("feedback"=>$id)); 309 310 //deleting the unfinished completeds 311 $DB->delete_records("feedback_completedtmp", array("feedback"=>$id)); 312 313 //deleting old events 314 $DB->delete_records('event', array('modulename'=>'feedback', 'instance'=>$id)); 315 return $DB->delete_records("feedback", array("id"=>$id)); 316 } 317 318 /** 319 * this is called after deleting all instances if the course will be deleted. 320 * only templates have to be deleted 321 * 322 * @global object 323 * @param object $course 324 * @return boolean 325 */ 326 function feedback_delete_course($course) { 327 global $DB; 328 329 //delete all templates of given course 330 return $DB->delete_records('feedback_template', array('course'=>$course->id)); 331 } 332 333 /** 334 * Return a small object with summary information about what a 335 * user has done with a given particular instance of this module 336 * Used for user activity reports. 337 * $return->time = the time they did it 338 * $return->info = a short text description 339 * 340 * @param object $course 341 * @param object $user 342 * @param object $mod 343 * @param object $feedback 344 * @return object 345 */ 346 function feedback_user_outline($course, $user, $mod, $feedback) { 347 return null; 348 } 349 350 /** 351 * Returns all users who has completed a specified feedback since a given time 352 * many thanks to Manolescu Dorel, who contributed these two functions 353 * 354 * @global object 355 * @global object 356 * @global object 357 * @global object 358 * @uses CONTEXT_MODULE 359 * @param array $activities Passed by reference 360 * @param int $index Passed by reference 361 * @param int $timemodified Timestamp 362 * @param int $courseid 363 * @param int $cmid 364 * @param int $userid 365 * @param int $groupid 366 * @return void 367 */ 368 function feedback_get_recent_mod_activity(&$activities, &$index, 369 $timemodified, $courseid, 370 $cmid, $userid="", $groupid="") { 371 372 global $CFG, $COURSE, $USER, $DB; 373 374 if ($COURSE->id == $courseid) { 375 $course = $COURSE; 376 } else { 377 $course = $DB->get_record('course', array('id'=>$courseid)); 378 } 379 380 $modinfo = get_fast_modinfo($course); 381 382 $cm = $modinfo->cms[$cmid]; 383 384 $sqlargs = array(); 385 386 $userfields = user_picture::fields('u', null, 'useridagain'); 387 $sql = " SELECT fk . * , fc . * , $userfields 388 FROM {feedback_completed} fc 389 JOIN {feedback} fk ON fk.id = fc.feedback 390 JOIN {user} u ON u.id = fc.userid "; 391 392 if ($groupid) { 393 $sql .= " JOIN {groups_members} gm ON gm.userid=u.id "; 394 } 395 396 $sql .= " WHERE fc.timemodified > ? AND fk.id = ? "; 397 $sqlargs[] = $timemodified; 398 $sqlargs[] = $cm->instance; 399 400 if ($userid) { 401 $sql .= " AND u.id = ? "; 402 $sqlargs[] = $userid; 403 } 404 405 if ($groupid) { 406 $sql .= " AND gm.groupid = ? "; 407 $sqlargs[] = $groupid; 408 } 409 410 if (!$feedbackitems = $DB->get_records_sql($sql, $sqlargs)) { 411 return; 412 } 413 414 $cm_context = context_module::instance($cm->id); 415 416 if (!has_capability('mod/feedback:view', $cm_context)) { 417 return; 418 } 419 420 $accessallgroups = has_capability('moodle/site:accessallgroups', $cm_context); 421 $viewfullnames = has_capability('moodle/site:viewfullnames', $cm_context); 422 $groupmode = groups_get_activity_groupmode($cm, $course); 423 424 $aname = format_string($cm->name, true); 425 foreach ($feedbackitems as $feedbackitem) { 426 if ($feedbackitem->userid != $USER->id) { 427 428 if ($groupmode == SEPARATEGROUPS and !$accessallgroups) { 429 $usersgroups = groups_get_all_groups($course->id, 430 $feedbackitem->userid, 431 $cm->groupingid); 432 if (!is_array($usersgroups)) { 433 continue; 434 } 435 $usersgroups = array_keys($usersgroups); 436 $intersect = array_intersect($usersgroups, $modinfo->get_groups($cm->groupingid)); 437 if (empty($intersect)) { 438 continue; 439 } 440 } 441 } 442 443 $tmpactivity = new stdClass(); 444 445 $tmpactivity->type = 'feedback'; 446 $tmpactivity->cmid = $cm->id; 447 $tmpactivity->name = $aname; 448 $tmpactivity->sectionnum= $cm->sectionnum; 449 $tmpactivity->timestamp = $feedbackitem->timemodified; 450 451 $tmpactivity->content = new stdClass(); 452 $tmpactivity->content->feedbackid = $feedbackitem->id; 453 $tmpactivity->content->feedbackuserid = $feedbackitem->userid; 454 455 $tmpactivity->user = user_picture::unalias($feedbackitem, null, 'useridagain'); 456 $tmpactivity->user->fullname = fullname($feedbackitem, $viewfullnames); 457 458 $activities[$index++] = $tmpactivity; 459 } 460 461 return; 462 } 463 464 /** 465 * Prints all users who has completed a specified feedback since a given time 466 * many thanks to Manolescu Dorel, who contributed these two functions 467 * 468 * @global object 469 * @param object $activity 470 * @param int $courseid 471 * @param string $detail 472 * @param array $modnames 473 * @return void Output is echo'd 474 */ 475 function feedback_print_recent_mod_activity($activity, $courseid, $detail, $modnames) { 476 global $CFG, $OUTPUT; 477 478 echo '<table border="0" cellpadding="3" cellspacing="0" class="forum-recent">'; 479 480 echo "<tr><td class=\"userpicture\" valign=\"top\">"; 481 echo $OUTPUT->user_picture($activity->user, array('courseid'=>$courseid)); 482 echo "</td><td>"; 483 484 if ($detail) { 485 $modname = $modnames[$activity->type]; 486 echo '<div class="title">'; 487 echo "<img src=\"" . $OUTPUT->pix_url('icon', $activity->type) . "\" ". 488 "class=\"icon\" alt=\"$modname\" />"; 489 echo "<a href=\"$CFG->wwwroot/mod/feedback/view.php?id={$activity->cmid}\">{$activity->name}</a>"; 490 echo '</div>'; 491 } 492 493 echo '<div class="title">'; 494 echo '</div>'; 495 496 echo '<div class="user">'; 497 echo "<a href=\"$CFG->wwwroot/user/view.php?id={$activity->user->id}&course=$courseid\">" 498 ."{$activity->user->fullname}</a> - ".userdate($activity->timestamp); 499 echo '</div>'; 500 501 echo "</td></tr></table>"; 502 503 return; 504 } 505 506 /** 507 * Obtains the automatic completion state for this feedback based on the condition 508 * in feedback settings. 509 * 510 * @param object $course Course 511 * @param object $cm Course-module 512 * @param int $userid User ID 513 * @param bool $type Type of comparison (or/and; can be used as return value if no conditions) 514 * @return bool True if completed, false if not, $type if conditions not set. 515 */ 516 function feedback_get_completion_state($course, $cm, $userid, $type) { 517 global $CFG, $DB; 518 519 // Get feedback details 520 $feedback = $DB->get_record('feedback', array('id'=>$cm->instance), '*', MUST_EXIST); 521 522 // If completion option is enabled, evaluate it and return true/false 523 if ($feedback->completionsubmit) { 524 $params = array('userid'=>$userid, 'feedback'=>$feedback->id); 525 return $DB->record_exists('feedback_tracking', $params); 526 } else { 527 // Completion option is not enabled so just return $type 528 return $type; 529 } 530 } 531 532 533 /** 534 * Print a detailed representation of what a user has done with 535 * a given particular instance of this module, for user activity reports. 536 * 537 * @param object $course 538 * @param object $user 539 * @param object $mod 540 * @param object $feedback 541 * @return bool 542 */ 543 function feedback_user_complete($course, $user, $mod, $feedback) { 544 return true; 545 } 546 547 /** 548 * @return bool true 549 */ 550 function feedback_cron () { 551 return true; 552 } 553 554 /** 555 * @return bool false 556 */ 557 function feedback_scale_used ($feedbackid, $scaleid) { 558 return false; 559 } 560 561 /** 562 * Checks if scale is being used by any instance of feedback 563 * 564 * This is used to find out if scale used anywhere 565 * @param $scaleid int 566 * @return boolean True if the scale is used by any assignment 567 */ 568 function feedback_scale_used_anywhere($scaleid) { 569 return false; 570 } 571 572 /** 573 * List the actions that correspond to a view of this module. 574 * This is used by the participation report. 575 * 576 * Note: This is not used by new logging system. Event with 577 * crud = 'r' and edulevel = LEVEL_PARTICIPATING will 578 * be considered as view action. 579 * 580 * @return array 581 */ 582 function feedback_get_view_actions() { 583 return array('view', 'view all'); 584 } 585 586 /** 587 * List the actions that correspond to a post of this module. 588 * This is used by the participation report. 589 * 590 * Note: This is not used by new logging system. Event with 591 * crud = ('c' || 'u' || 'd') and edulevel = LEVEL_PARTICIPATING 592 * will be considered as post action. 593 * 594 * @return array 595 */ 596 function feedback_get_post_actions() { 597 return array('submit'); 598 } 599 600 /** 601 * This function is used by the reset_course_userdata function in moodlelib. 602 * This function will remove all responses from the specified feedback 603 * and clean up any related data. 604 * 605 * @global object 606 * @global object 607 * @uses FEEDBACK_RESETFORM_RESET 608 * @uses FEEDBACK_RESETFORM_DROP 609 * @param object $data the data submitted from the reset course. 610 * @return array status array 611 */ 612 function feedback_reset_userdata($data) { 613 global $CFG, $DB; 614 615 $resetfeedbacks = array(); 616 $dropfeedbacks = array(); 617 $status = array(); 618 $componentstr = get_string('modulenameplural', 'feedback'); 619 620 //get the relevant entries from $data 621 foreach ($data as $key => $value) { 622 switch(true) { 623 case substr($key, 0, strlen(FEEDBACK_RESETFORM_RESET)) == FEEDBACK_RESETFORM_RESET: 624 if ($value == 1) { 625 $templist = explode('_', $key); 626 if (isset($templist[3])) { 627 $resetfeedbacks[] = intval($templist[3]); 628 } 629 } 630 break; 631 case substr($key, 0, strlen(FEEDBACK_RESETFORM_DROP)) == FEEDBACK_RESETFORM_DROP: 632 if ($value == 1) { 633 $templist = explode('_', $key); 634 if (isset($templist[3])) { 635 $dropfeedbacks[] = intval($templist[3]); 636 } 637 } 638 break; 639 } 640 } 641 642 //reset the selected feedbacks 643 foreach ($resetfeedbacks as $id) { 644 $feedback = $DB->get_record('feedback', array('id'=>$id)); 645 feedback_delete_all_completeds($id); 646 $status[] = array('component'=>$componentstr.':'.$feedback->name, 647 'item'=>get_string('resetting_data', 'feedback'), 648 'error'=>false); 649 } 650 651 return $status; 652 } 653 654 /** 655 * Called by course/reset.php 656 * 657 * @global object 658 * @uses FEEDBACK_RESETFORM_RESET 659 * @param object $mform form passed by reference 660 */ 661 function feedback_reset_course_form_definition(&$mform) { 662 global $COURSE, $DB; 663 664 $mform->addElement('header', 'feedbackheader', get_string('modulenameplural', 'feedback')); 665 666 if (!$feedbacks = $DB->get_records('feedback', array('course'=>$COURSE->id), 'name')) { 667 return; 668 } 669 670 $mform->addElement('static', 'hint', get_string('resetting_data', 'feedback')); 671 foreach ($feedbacks as $feedback) { 672 $mform->addElement('checkbox', FEEDBACK_RESETFORM_RESET.$feedback->id, $feedback->name); 673 } 674 } 675 676 /** 677 * Course reset form defaults. 678 * 679 * @global object 680 * @uses FEEDBACK_RESETFORM_RESET 681 * @param object $course 682 */ 683 function feedback_reset_course_form_defaults($course) { 684 global $DB; 685 686 $return = array(); 687 if (!$feedbacks = $DB->get_records('feedback', array('course'=>$course->id), 'name')) { 688 return; 689 } 690 foreach ($feedbacks as $feedback) { 691 $return[FEEDBACK_RESETFORM_RESET.$feedback->id] = true; 692 } 693 return $return; 694 } 695 696 /** 697 * Called by course/reset.php and shows the formdata by coursereset. 698 * it prints checkboxes for each feedback available at the given course 699 * there are two checkboxes: 700 * 1) delete userdata and keep the feedback 701 * 2) delete userdata and drop the feedback 702 * 703 * @global object 704 * @uses FEEDBACK_RESETFORM_RESET 705 * @uses FEEDBACK_RESETFORM_DROP 706 * @param object $course 707 * @return void 708 */ 709 function feedback_reset_course_form($course) { 710 global $DB, $OUTPUT; 711 712 echo get_string('resetting_feedbacks', 'feedback'); echo ':<br />'; 713 if (!$feedbacks = $DB->get_records('feedback', array('course'=>$course->id), 'name')) { 714 return; 715 } 716 717 foreach ($feedbacks as $feedback) { 718 echo '<p>'; 719 echo get_string('name', 'feedback').': '.$feedback->name.'<br />'; 720 echo html_writer::checkbox(FEEDBACK_RESETFORM_RESET.$feedback->id, 721 1, true, 722 get_string('resetting_data', 'feedback')); 723 echo '<br />'; 724 echo html_writer::checkbox(FEEDBACK_RESETFORM_DROP.$feedback->id, 725 1, false, 726 get_string('drop_feedback', 'feedback')); 727 echo '</p>'; 728 } 729 } 730 731 /** 732 * This gets an array with default options for the editor 733 * 734 * @return array the options 735 */ 736 function feedback_get_editor_options() { 737 return array('maxfiles' => EDITOR_UNLIMITED_FILES, 738 'trusttext'=>true); 739 } 740 741 /** 742 * This creates new events given as timeopen and closeopen by $feedback. 743 * 744 * @global object 745 * @param object $feedback 746 * @return void 747 */ 748 function feedback_set_events($feedback) { 749 global $DB; 750 751 // adding the feedback to the eventtable (I have seen this at quiz-module) 752 $DB->delete_records('event', array('modulename'=>'feedback', 'instance'=>$feedback->id)); 753 754 if (!isset($feedback->coursemodule)) { 755 $cm = get_coursemodule_from_id('feedback', $feedback->id); 756 $feedback->coursemodule = $cm->id; 757 } 758 759 // the open-event 760 if ($feedback->timeopen > 0) { 761 $event = new stdClass(); 762 $event->name = get_string('start', 'feedback').' '.$feedback->name; 763 $event->description = format_module_intro('feedback', $feedback, $feedback->coursemodule); 764 $event->courseid = $feedback->course; 765 $event->groupid = 0; 766 $event->userid = 0; 767 $event->modulename = 'feedback'; 768 $event->instance = $feedback->id; 769 $event->eventtype = 'open'; 770 $event->timestart = $feedback->timeopen; 771 $event->visible = instance_is_visible('feedback', $feedback); 772 if ($feedback->timeclose > 0) { 773 $event->timeduration = ($feedback->timeclose - $feedback->timeopen); 774 } else { 775 $event->timeduration = 0; 776 } 777 778 calendar_event::create($event); 779 } 780 781 // the close-event 782 if ($feedback->timeclose > 0) { 783 $event = new stdClass(); 784 $event->name = get_string('stop', 'feedback').' '.$feedback->name; 785 $event->description = format_module_intro('feedback', $feedback, $feedback->coursemodule); 786 $event->courseid = $feedback->course; 787 $event->groupid = 0; 788 $event->userid = 0; 789 $event->modulename = 'feedback'; 790 $event->instance = $feedback->id; 791 $event->eventtype = 'close'; 792 $event->timestart = $feedback->timeclose; 793 $event->visible = instance_is_visible('feedback', $feedback); 794 $event->timeduration = 0; 795 796 calendar_event::create($event); 797 } 798 } 799 800 /** 801 * this function is called by {@link feedback_delete_userdata()} 802 * it drops the feedback-instance from the course_module table 803 * 804 * @global object 805 * @param int $id the id from the coursemodule 806 * @return boolean 807 */ 808 function feedback_delete_course_module($id) { 809 global $DB; 810 811 if (!$cm = $DB->get_record('course_modules', array('id'=>$id))) { 812 return true; 813 } 814 return $DB->delete_records('course_modules', array('id'=>$cm->id)); 815 } 816 817 818 819 //////////////////////////////////////////////// 820 //functions to handle capabilities 821 //////////////////////////////////////////////// 822 823 /** 824 * returns the context-id related to the given coursemodule-id 825 * 826 * @staticvar object $context 827 * @param int $cmid the coursemodule-id 828 * @return object $context 829 */ 830 function feedback_get_context($cmid) { 831 static $context; 832 833 if (isset($context)) { 834 return $context; 835 } 836 837 $context = context_module::instance($cmid); 838 return $context; 839 } 840 841 /** 842 * returns true if the current role is faked by switching role feature 843 * 844 * @global object 845 * @return boolean 846 */ 847 function feedback_check_is_switchrole() { 848 global $USER; 849 if (isset($USER->switchrole) AND 850 is_array($USER->switchrole) AND 851 count($USER->switchrole) > 0) { 852 853 return true; 854 } 855 return false; 856 } 857 858 /** 859 * count users which have not completed the feedback 860 * 861 * @global object 862 * @uses CONTEXT_MODULE 863 * @param cm_info $cm Course-module object 864 * @param int $group single groupid 865 * @param string $sort 866 * @param int $startpage 867 * @param int $pagecount 868 * @return object the userrecords 869 */ 870 function feedback_get_incomplete_users(cm_info $cm, 871 $group = false, 872 $sort = '', 873 $startpage = false, 874 $pagecount = false) { 875 876 global $DB; 877 878 $context = context_module::instance($cm->id); 879 880 //first get all user who can complete this feedback 881 $cap = 'mod/feedback:complete'; 882 $fields = 'u.id, u.username'; 883 if (!$allusers = get_users_by_capability($context, 884 $cap, 885 $fields, 886 $sort, 887 '', 888 '', 889 $group, 890 '', 891 true)) { 892 return false; 893 } 894 // Filter users that are not in the correct group/grouping. 895 $info = new \core_availability\info_module($cm); 896 $allusers = $info->filter_user_list($allusers); 897 898 $allusers = array_keys($allusers); 899 900 //now get all completeds 901 $params = array('feedback'=>$cm->instance); 902 if (!$completedusers = $DB->get_records_menu('feedback_completed', $params, '', 'userid,id')) { 903 return $allusers; 904 } 905 $completedusers = array_keys($completedusers); 906 907 //now strike all completedusers from allusers 908 $allusers = array_diff($allusers, $completedusers); 909 910 //for paging I use array_slice() 911 if ($startpage !== false AND $pagecount !== false) { 912 $allusers = array_slice($allusers, $startpage, $pagecount); 913 } 914 915 return $allusers; 916 } 917 918 /** 919 * count users which have not completed the feedback 920 * 921 * @global object 922 * @param object $cm 923 * @param int $group single groupid 924 * @return int count of userrecords 925 */ 926 function feedback_count_incomplete_users($cm, $group = false) { 927 if ($allusers = feedback_get_incomplete_users($cm, $group)) { 928 return count($allusers); 929 } 930 return 0; 931 } 932 933 /** 934 * count users which have completed a feedback 935 * 936 * @global object 937 * @uses FEEDBACK_ANONYMOUS_NO 938 * @param object $cm 939 * @param int $group single groupid 940 * @return int count of userrecords 941 */ 942 function feedback_count_complete_users($cm, $group = false) { 943 global $DB; 944 945 $params = array(FEEDBACK_ANONYMOUS_NO, $cm->instance); 946 947 $fromgroup = ''; 948 $wheregroup = ''; 949 if ($group) { 950 $fromgroup = ', {groups_members} g'; 951 $wheregroup = ' AND g.groupid = ? AND g.userid = c.userid'; 952 $params[] = $group; 953 } 954 955 $sql = 'SELECT COUNT(u.id) FROM {user} u, {feedback_completed} c'.$fromgroup.' 956 WHERE anonymous_response = ? AND u.id = c.userid AND c.feedback = ? 957 '.$wheregroup; 958 959 return $DB->count_records_sql($sql, $params); 960 961 } 962 963 /** 964 * get users which have completed a feedback 965 * 966 * @global object 967 * @uses CONTEXT_MODULE 968 * @uses FEEDBACK_ANONYMOUS_NO 969 * @param object $cm 970 * @param int $group single groupid 971 * @param string $where a sql where condition (must end with " AND ") 972 * @param array parameters used in $where 973 * @param string $sort a table field 974 * @param int $startpage 975 * @param int $pagecount 976 * @return object the userrecords 977 */ 978 function feedback_get_complete_users($cm, 979 $group = false, 980 $where = '', 981 array $params = null, 982 $sort = '', 983 $startpage = false, 984 $pagecount = false) { 985 986 global $DB; 987 988 $context = context_module::instance($cm->id); 989 990 $params = (array)$params; 991 992 $params['anon'] = FEEDBACK_ANONYMOUS_NO; 993 $params['instance'] = $cm->instance; 994 995 $fromgroup = ''; 996 $wheregroup = ''; 997 if ($group) { 998 $fromgroup = ', {groups_members} g'; 999 $wheregroup = ' AND g.groupid = :group AND g.userid = c.userid'; 1000 $params['group'] = $group; 1001 } 1002 1003 if ($sort) { 1004 $sortsql = ' ORDER BY '.$sort; 1005 } else { 1006 $sortsql = ''; 1007 } 1008 1009 $ufields = user_picture::fields('u'); 1010 $sql = 'SELECT DISTINCT '.$ufields.', c.timemodified as completed_timemodified 1011 FROM {user} u, {feedback_completed} c '.$fromgroup.' 1012 WHERE '.$where.' anonymous_response = :anon 1013 AND u.id = c.userid 1014 AND c.feedback = :instance 1015 '.$wheregroup.$sortsql; 1016 1017 if ($startpage === false OR $pagecount === false) { 1018 $startpage = false; 1019 $pagecount = false; 1020 } 1021 return $DB->get_records_sql($sql, $params, $startpage, $pagecount); 1022 } 1023 1024 /** 1025 * get users which have the viewreports-capability 1026 * 1027 * @uses CONTEXT_MODULE 1028 * @param int $cmid 1029 * @param mixed $groups single groupid or array of groupids - group(s) user is in 1030 * @return object the userrecords 1031 */ 1032 function feedback_get_viewreports_users($cmid, $groups = false) { 1033 1034 $context = context_module::instance($cmid); 1035 1036 //description of the call below: 1037 //get_users_by_capability($context, $capability, $fields='', $sort='', $limitfrom='', 1038 // $limitnum='', $groups='', $exceptions='', $doanything=true) 1039 return get_users_by_capability($context, 1040 'mod/feedback:viewreports', 1041 '', 1042 'lastname', 1043 '', 1044 '', 1045 $groups, 1046 '', 1047 false); 1048 } 1049 1050 /** 1051 * get users which have the receivemail-capability 1052 * 1053 * @uses CONTEXT_MODULE 1054 * @param int $cmid 1055 * @param mixed $groups single groupid or array of groupids - group(s) user is in 1056 * @return object the userrecords 1057 */ 1058 function feedback_get_receivemail_users($cmid, $groups = false) { 1059 1060 $context = context_module::instance($cmid); 1061 1062 //description of the call below: 1063 //get_users_by_capability($context, $capability, $fields='', $sort='', $limitfrom='', 1064 // $limitnum='', $groups='', $exceptions='', $doanything=true) 1065 return get_users_by_capability($context, 1066 'mod/feedback:receivemail', 1067 '', 1068 'lastname', 1069 '', 1070 '', 1071 $groups, 1072 '', 1073 false); 1074 } 1075 1076 //////////////////////////////////////////////// 1077 //functions to handle the templates 1078 //////////////////////////////////////////////// 1079 //////////////////////////////////////////////// 1080 1081 /** 1082 * creates a new template-record. 1083 * 1084 * @global object 1085 * @param int $courseid 1086 * @param string $name the name of template shown in the templatelist 1087 * @param int $ispublic 0:privat 1:public 1088 * @return int the new templateid 1089 */ 1090 function feedback_create_template($courseid, $name, $ispublic = 0) { 1091 global $DB; 1092 1093 $templ = new stdClass(); 1094 $templ->course = ($ispublic ? 0 : $courseid); 1095 $templ->name = $name; 1096 $templ->ispublic = $ispublic; 1097 1098 $templid = $DB->insert_record('feedback_template', $templ); 1099 return $DB->get_record('feedback_template', array('id'=>$templid)); 1100 } 1101 1102 /** 1103 * creates new template items. 1104 * all items will be copied and the attribute feedback will be set to 0 1105 * and the attribute template will be set to the new templateid 1106 * 1107 * @global object 1108 * @uses CONTEXT_MODULE 1109 * @uses CONTEXT_COURSE 1110 * @param object $feedback 1111 * @param string $name the name of template shown in the templatelist 1112 * @param int $ispublic 0:privat 1:public 1113 * @return boolean 1114 */ 1115 function feedback_save_as_template($feedback, $name, $ispublic = 0) { 1116 global $DB; 1117 $fs = get_file_storage(); 1118 1119 if (!$feedbackitems = $DB->get_records('feedback_item', array('feedback'=>$feedback->id))) { 1120 return false; 1121 } 1122 1123 if (!$newtempl = feedback_create_template($feedback->course, $name, $ispublic)) { 1124 return false; 1125 } 1126 1127 //files in the template_item are in the context of the current course or 1128 //if the template is public the files are in the system context 1129 //files in the feedback_item are in the feedback_context of the feedback 1130 if ($ispublic) { 1131 $s_context = context_system::instance(); 1132 } else { 1133 $s_context = context_course::instance($newtempl->course); 1134 } 1135 $cm = get_coursemodule_from_instance('feedback', $feedback->id); 1136 $f_context = context_module::instance($cm->id); 1137 1138 //create items of this new template 1139 //depend items we are storing temporary in an mapping list array(new id => dependitem) 1140 //we also store a mapping of all items array(oldid => newid) 1141 $dependitemsmap = array(); 1142 $itembackup = array(); 1143 foreach ($feedbackitems as $item) { 1144 1145 $t_item = clone($item); 1146 1147 unset($t_item->id); 1148 $t_item->feedback = 0; 1149 $t_item->template = $newtempl->id; 1150 $t_item->id = $DB->insert_record('feedback_item', $t_item); 1151 //copy all included files to the feedback_template filearea 1152 $itemfiles = $fs->get_area_files($f_context->id, 1153 'mod_feedback', 1154 'item', 1155 $item->id, 1156 "id", 1157 false); 1158 if ($itemfiles) { 1159 foreach ($itemfiles as $ifile) { 1160 $file_record = new stdClass(); 1161 $file_record->contextid = $s_context->id; 1162 $file_record->component = 'mod_feedback'; 1163 $file_record->filearea = 'template'; 1164 $file_record->itemid = $t_item->id; 1165 $fs->create_file_from_storedfile($file_record, $ifile); 1166 } 1167 } 1168 1169 $itembackup[$item->id] = $t_item->id; 1170 if ($t_item->dependitem) { 1171 $dependitemsmap[$t_item->id] = $t_item->dependitem; 1172 } 1173 1174 } 1175 1176 //remapping the dependency 1177 foreach ($dependitemsmap as $key => $dependitem) { 1178 $newitem = $DB->get_record('feedback_item', array('id'=>$key)); 1179 $newitem->dependitem = $itembackup[$newitem->dependitem]; 1180 $DB->update_record('feedback_item', $newitem); 1181 } 1182 1183 return true; 1184 } 1185 1186 /** 1187 * deletes all feedback_items related to the given template id 1188 * 1189 * @global object 1190 * @uses CONTEXT_COURSE 1191 * @param object $template the template 1192 * @return void 1193 */ 1194 function feedback_delete_template($template) { 1195 global $DB; 1196 1197 //deleting the files from the item is done by feedback_delete_item 1198 if ($t_items = $DB->get_records("feedback_item", array("template"=>$template->id))) { 1199 foreach ($t_items as $t_item) { 1200 feedback_delete_item($t_item->id, false, $template); 1201 } 1202 } 1203 $DB->delete_records("feedback_template", array("id"=>$template->id)); 1204 } 1205 1206 /** 1207 * creates new feedback_item-records from template. 1208 * if $deleteold is set true so the existing items of the given feedback will be deleted 1209 * if $deleteold is set false so the new items will be appanded to the old items 1210 * 1211 * @global object 1212 * @uses CONTEXT_COURSE 1213 * @uses CONTEXT_MODULE 1214 * @param object $feedback 1215 * @param int $templateid 1216 * @param boolean $deleteold 1217 */ 1218 function feedback_items_from_template($feedback, $templateid, $deleteold = false) { 1219 global $DB, $CFG; 1220 1221 require_once($CFG->libdir.'/completionlib.php'); 1222 1223 $fs = get_file_storage(); 1224 1225 if (!$template = $DB->get_record('feedback_template', array('id'=>$templateid))) { 1226 return false; 1227 } 1228 //get all templateitems 1229 if (!$templitems = $DB->get_records('feedback_item', array('template'=>$templateid))) { 1230 return false; 1231 } 1232 1233 //files in the template_item are in the context of the current course 1234 //files in the feedback_item are in the feedback_context of the feedback 1235 if ($template->ispublic) { 1236 $s_context = context_system::instance(); 1237 } else { 1238 $s_context = context_course::instance($feedback->course); 1239 } 1240 $course = $DB->get_record('course', array('id'=>$feedback->course)); 1241 $cm = get_coursemodule_from_instance('feedback', $feedback->id); 1242 $f_context = context_module::instance($cm->id); 1243 1244 //if deleteold then delete all old items before 1245 //get all items 1246 if ($deleteold) { 1247 if ($feedbackitems = $DB->get_records('feedback_item', array('feedback'=>$feedback->id))) { 1248 //delete all items of this feedback 1249 foreach ($feedbackitems as $item) { 1250 feedback_delete_item($item->id, false); 1251 } 1252 //delete tracking-data 1253 $DB->delete_records('feedback_tracking', array('feedback'=>$feedback->id)); 1254 1255 $params = array('feedback'=>$feedback->id); 1256 if ($completeds = $DB->get_records('feedback_completed', $params)) { 1257 $completion = new completion_info($course); 1258 foreach ($completeds as $completed) { 1259 // Update completion state 1260 if ($completion->is_enabled($cm) && $feedback->completionsubmit) { 1261 $completion->update_state($cm, COMPLETION_INCOMPLETE, $completed->userid); 1262 } 1263 $DB->delete_records('feedback_completed', array('id'=>$completed->id)); 1264 } 1265 } 1266 $DB->delete_records('feedback_completedtmp', array('feedback'=>$feedback->id)); 1267 } 1268 $positionoffset = 0; 1269 } else { 1270 //if the old items are kept the new items will be appended 1271 //therefor the new position has an offset 1272 $positionoffset = $DB->count_records('feedback_item', array('feedback'=>$feedback->id)); 1273 } 1274 1275 //create items of this new template 1276 //depend items we are storing temporary in an mapping list array(new id => dependitem) 1277 //we also store a mapping of all items array(oldid => newid) 1278 $dependitemsmap = array(); 1279 $itembackup = array(); 1280 foreach ($templitems as $t_item) { 1281 $item = clone($t_item); 1282 unset($item->id); 1283 $item->feedback = $feedback->id; 1284 $item->template = 0; 1285 $item->position = $item->position + $positionoffset; 1286 1287 $item->id = $DB->insert_record('feedback_item', $item); 1288 1289 //moving the files to the new item 1290 $templatefiles = $fs->get_area_files($s_context->id, 1291 'mod_feedback', 1292 'template', 1293 $t_item->id, 1294 "id", 1295 false); 1296 if ($templatefiles) { 1297 foreach ($templatefiles as $tfile) { 1298 $file_record = new stdClass(); 1299 $file_record->contextid = $f_context->id; 1300 $file_record->component = 'mod_feedback'; 1301 $file_record->filearea = 'item'; 1302 $file_record->itemid = $item->id; 1303 $fs->create_file_from_storedfile($file_record, $tfile); 1304 } 1305 } 1306 1307 $itembackup[$t_item->id] = $item->id; 1308 if ($item->dependitem) { 1309 $dependitemsmap[$item->id] = $item->dependitem; 1310 } 1311 } 1312 1313 //remapping the dependency 1314 foreach ($dependitemsmap as $key => $dependitem) { 1315 $newitem = $DB->get_record('feedback_item', array('id'=>$key)); 1316 $newitem->dependitem = $itembackup[$newitem->dependitem]; 1317 $DB->update_record('feedback_item', $newitem); 1318 } 1319 } 1320 1321 /** 1322 * get the list of available templates. 1323 * if the $onlyown param is set true so only templates from own course will be served 1324 * this is important for droping templates 1325 * 1326 * @global object 1327 * @param object $course 1328 * @param string $onlyownorpublic 1329 * @return array the template recordsets 1330 */ 1331 function feedback_get_template_list($course, $onlyownorpublic = '') { 1332 global $DB, $CFG; 1333 1334 switch($onlyownorpublic) { 1335 case '': 1336 $templates = $DB->get_records_select('feedback_template', 1337 'course = ? OR ispublic = 1', 1338 array($course->id), 1339 'name'); 1340 break; 1341 case 'own': 1342 $templates = $DB->get_records('feedback_template', 1343 array('course'=>$course->id), 1344 'name'); 1345 break; 1346 case 'public': 1347 $templates = $DB->get_records('feedback_template', array('ispublic'=>1), 'name'); 1348 break; 1349 } 1350 return $templates; 1351 } 1352 1353 //////////////////////////////////////////////// 1354 //Handling der Items 1355 //////////////////////////////////////////////// 1356 //////////////////////////////////////////////// 1357 1358 /** 1359 * load the lib.php from item-plugin-dir and returns the instance of the itemclass 1360 * 1361 * @global object 1362 * @param object $item 1363 * @return object the instanz of itemclass 1364 */ 1365 function feedback_get_item_class($typ) { 1366 global $CFG; 1367 1368 //get the class of item-typ 1369 $itemclass = 'feedback_item_'.$typ; 1370 //get the instance of item-class 1371 if (!class_exists($itemclass)) { 1372 require_once($CFG->dirroot.'/mod/feedback/item/'.$typ.'/lib.php'); 1373 } 1374 return new $itemclass(); 1375 } 1376 1377 /** 1378 * load the available item plugins from given subdirectory of $CFG->dirroot 1379 * the default is "mod/feedback/item" 1380 * 1381 * @global object 1382 * @param string $dir the subdir 1383 * @return array pluginnames as string 1384 */ 1385 function feedback_load_feedback_items($dir = 'mod/feedback/item') { 1386 global $CFG; 1387 $names = get_list_of_plugins($dir); 1388 $ret_names = array(); 1389 1390 foreach ($names as $name) { 1391 require_once($CFG->dirroot.'/'.$dir.'/'.$name.'/lib.php'); 1392 if (class_exists('feedback_item_'.$name)) { 1393 $ret_names[] = $name; 1394 } 1395 } 1396 return $ret_names; 1397 } 1398 1399 /** 1400 * load the available item plugins to use as dropdown-options 1401 * 1402 * @global object 1403 * @return array pluginnames as string 1404 */ 1405 function feedback_load_feedback_items_options() { 1406 global $CFG; 1407 1408 $feedback_options = array("pagebreak" => get_string('add_pagebreak', 'feedback')); 1409 1410 if (!$feedback_names = feedback_load_feedback_items('mod/feedback/item')) { 1411 return array(); 1412 } 1413 1414 foreach ($feedback_names as $fn) { 1415 $feedback_options[$fn] = get_string($fn, 'feedback'); 1416 } 1417 asort($feedback_options); 1418 $feedback_options = array_merge( array(' ' => get_string('select')), $feedback_options ); 1419 return $feedback_options; 1420 } 1421 1422 /** 1423 * load the available items for the depend item dropdown list shown in the edit_item form 1424 * 1425 * @global object 1426 * @param object $feedback 1427 * @param object $item the item of the edit_item form 1428 * @return array all items except the item $item, labels and pagebreaks 1429 */ 1430 function feedback_get_depend_candidates_for_item($feedback, $item) { 1431 global $DB; 1432 //all items for dependitem 1433 $where = "feedback = ? AND typ != 'pagebreak' AND hasvalue = 1"; 1434 $params = array($feedback->id); 1435 if (isset($item->id) AND $item->id) { 1436 $where .= ' AND id != ?'; 1437 $params[] = $item->id; 1438 } 1439 $dependitems = array(0 => get_string('choose')); 1440 $feedbackitems = $DB->get_records_select_menu('feedback_item', 1441 $where, 1442 $params, 1443 'position', 1444 'id, label'); 1445 1446 if (!$feedbackitems) { 1447 return $dependitems; 1448 } 1449 //adding the choose-option 1450 foreach ($feedbackitems as $key => $val) { 1451 $dependitems[$key] = $val; 1452 } 1453 return $dependitems; 1454 } 1455 1456 /** 1457 * creates a new item-record 1458 * 1459 * @global object 1460 * @param object $data the data from edit_item_form 1461 * @return int the new itemid 1462 */ 1463 function feedback_create_item($data) { 1464 global $DB; 1465 1466 $item = new stdClass(); 1467 $item->feedback = $data->feedbackid; 1468 1469 $item->template=0; 1470 if (isset($data->templateid)) { 1471 $item->template = intval($data->templateid); 1472 } 1473 1474 $itemname = trim($data->itemname); 1475 $item->name = ($itemname ? $data->itemname : get_string('no_itemname', 'feedback')); 1476 1477 if (!empty($data->itemlabel)) { 1478 $item->label = trim($data->itemlabel); 1479 } else { 1480 $item->label = get_string('no_itemlabel', 'feedback'); 1481 } 1482 1483 $itemobj = feedback_get_item_class($data->typ); 1484 $item->presentation = ''; //the date comes from postupdate() of the itemobj 1485 1486 $item->hasvalue = $itemobj->get_hasvalue(); 1487 1488 $item->typ = $data->typ; 1489 $item->position = $data->position; 1490 1491 $item->required=0; 1492 if (!empty($data->required)) { 1493 $item->required = $data->required; 1494 } 1495 1496 $item->id = $DB->insert_record('feedback_item', $item); 1497 1498 //move all itemdata to the data 1499 $data->id = $item->id; 1500 $data->feedback = $item->feedback; 1501 $data->name = $item->name; 1502 $data->label = $item->label; 1503 $data->required = $item->required; 1504 return $itemobj->postupdate($data); 1505 } 1506 1507 /** 1508 * save the changes of a given item. 1509 * 1510 * @global object 1511 * @param object $item 1512 * @return boolean 1513 */ 1514 function feedback_update_item($item) { 1515 global $DB; 1516 return $DB->update_record("feedback_item", $item); 1517 } 1518 1519 /** 1520 * deletes an item and also deletes all related values 1521 * 1522 * @global object 1523 * @uses CONTEXT_MODULE 1524 * @param int $itemid 1525 * @param boolean $renumber should the kept items renumbered Yes/No 1526 * @param object $template if the template is given so the items are bound to it 1527 * @return void 1528 */ 1529 function feedback_delete_item($itemid, $renumber = true, $template = false) { 1530 global $DB; 1531 1532 $item = $DB->get_record('feedback_item', array('id'=>$itemid)); 1533 1534 //deleting the files from the item 1535 $fs = get_file_storage(); 1536 1537 if ($template) { 1538 if ($template->ispublic) { 1539 $context = context_system::instance(); 1540 } else { 1541 $context = context_course::instance($template->course); 1542 } 1543 $templatefiles = $fs->get_area_files($context->id, 1544 'mod_feedback', 1545 'template', 1546 $item->id, 1547 "id", 1548 false); 1549 1550 if ($templatefiles) { 1551 $fs->delete_area_files($context->id, 'mod_feedback', 'template', $item->id); 1552 } 1553 } else { 1554 if (!$cm = get_coursemodule_from_instance('feedback', $item->feedback)) { 1555 return false; 1556 } 1557 $context = context_module::instance($cm->id); 1558 1559 $itemfiles = $fs->get_area_files($context->id, 1560 'mod_feedback', 1561 'item', 1562 $item->id, 1563 "id", false); 1564 1565 if ($itemfiles) { 1566 $fs->delete_area_files($context->id, 'mod_feedback', 'item', $item->id); 1567 } 1568 } 1569 1570 $DB->delete_records("feedback_value", array("item"=>$itemid)); 1571 $DB->delete_records("feedback_valuetmp", array("item"=>$itemid)); 1572 1573 //remove all depends 1574 $DB->set_field('feedback_item', 'dependvalue', '', array('dependitem'=>$itemid)); 1575 $DB->set_field('feedback_item', 'dependitem', 0, array('dependitem'=>$itemid)); 1576 1577 $DB->delete_records("feedback_item", array("id"=>$itemid)); 1578 if ($renumber) { 1579 feedback_renumber_items($item->feedback); 1580 } 1581 } 1582 1583 /** 1584 * deletes all items of the given feedbackid 1585 * 1586 * @global object 1587 * @param int $feedbackid 1588 * @return void 1589 */ 1590 function feedback_delete_all_items($feedbackid) { 1591 global $DB, $CFG; 1592 require_once($CFG->libdir.'/completionlib.php'); 1593 1594 if (!$feedback = $DB->get_record('feedback', array('id'=>$feedbackid))) { 1595 return false; 1596 } 1597 1598 if (!$cm = get_coursemodule_from_instance('feedback', $feedback->id)) { 1599 return false; 1600 } 1601 1602 if (!$course = $DB->get_record('course', array('id'=>$feedback->course))) { 1603 return false; 1604 } 1605 1606 if (!$items = $DB->get_records('feedback_item', array('feedback'=>$feedbackid))) { 1607 return; 1608 } 1609 foreach ($items as $item) { 1610 feedback_delete_item($item->id, false); 1611 } 1612 if ($completeds = $DB->get_records('feedback_completed', array('feedback'=>$feedback->id))) { 1613 $completion = new completion_info($course); 1614 foreach ($completeds as $completed) { 1615 // Update completion state 1616 if ($completion->is_enabled($cm) && $feedback->completionsubmit) { 1617 $completion->update_state($cm, COMPLETION_INCOMPLETE, $completed->userid); 1618 } 1619 $DB->delete_records('feedback_completed', array('id'=>$completed->id)); 1620 } 1621 } 1622 1623 $DB->delete_records('feedback_completedtmp', array('feedback'=>$feedbackid)); 1624 1625 } 1626 1627 /** 1628 * this function toggled the item-attribute required (yes/no) 1629 * 1630 * @global object 1631 * @param object $item 1632 * @return boolean 1633 */ 1634 function feedback_switch_item_required($item) { 1635 global $DB, $CFG; 1636 1637 $itemobj = feedback_get_item_class($item->typ); 1638 1639 if ($itemobj->can_switch_require()) { 1640 $new_require_val = (int)!(bool)$item->required; 1641 $params = array('id'=>$item->id); 1642 $DB->set_field('feedback_item', 'required', $new_require_val, $params); 1643 } 1644 return true; 1645 } 1646 1647 /** 1648 * renumbers all items of the given feedbackid 1649 * 1650 * @global object 1651 * @param int $feedbackid 1652 * @return void 1653 */ 1654 function feedback_renumber_items($feedbackid) { 1655 global $DB; 1656 1657 $items = $DB->get_records('feedback_item', array('feedback'=>$feedbackid), 'position'); 1658 $pos = 1; 1659 if ($items) { 1660 foreach ($items as $item) { 1661 $DB->set_field('feedback_item', 'position', $pos, array('id'=>$item->id)); 1662 $pos++; 1663 } 1664 } 1665 } 1666 1667 /** 1668 * this decreases the position of the given item 1669 * 1670 * @global object 1671 * @param object $item 1672 * @return bool 1673 */ 1674 function feedback_moveup_item($item) { 1675 global $DB; 1676 1677 if ($item->position == 1) { 1678 return true; 1679 } 1680 1681 $params = array('feedback'=>$item->feedback); 1682 if (!$items = $DB->get_records('feedback_item', $params, 'position')) { 1683 return false; 1684 } 1685 1686 $itembefore = null; 1687 foreach ($items as $i) { 1688 if ($i->id == $item->id) { 1689 if (is_null($itembefore)) { 1690 return true; 1691 } 1692 $itembefore->position = $item->position; 1693 $item->position--; 1694 feedback_update_item($itembefore); 1695 feedback_update_item($item); 1696 feedback_renumber_items($item->feedback); 1697 return true; 1698 } 1699 $itembefore = $i; 1700 } 1701 return false; 1702 } 1703 1704 /** 1705 * this increased the position of the given item 1706 * 1707 * @global object 1708 * @param object $item 1709 * @return bool 1710 */ 1711 function feedback_movedown_item($item) { 1712 global $DB; 1713 1714 $params = array('feedback'=>$item->feedback); 1715 if (!$items = $DB->get_records('feedback_item', $params, 'position')) { 1716 return false; 1717 } 1718 1719 $movedownitem = null; 1720 foreach ($items as $i) { 1721 if (!is_null($movedownitem) AND $movedownitem->id == $item->id) { 1722 $movedownitem->position = $i->position; 1723 $i->position--; 1724 feedback_update_item($movedownitem); 1725 feedback_update_item($i); 1726 feedback_renumber_items($item->feedback); 1727 return true; 1728 } 1729 $movedownitem = $i; 1730 } 1731 return false; 1732 } 1733 1734 /** 1735 * here the position of the given item will be set to the value in $pos 1736 * 1737 * @global object 1738 * @param object $moveitem 1739 * @param int $pos 1740 * @return boolean 1741 */ 1742 function feedback_move_item($moveitem, $pos) { 1743 global $DB; 1744 1745 $params = array('feedback'=>$moveitem->feedback); 1746 if (!$allitems = $DB->get_records('feedback_item', $params, 'position')) { 1747 return false; 1748 } 1749 if (is_array($allitems)) { 1750 $index = 1; 1751 foreach ($allitems as $item) { 1752 if ($index == $pos) { 1753 $index++; 1754 } 1755 if ($item->id == $moveitem->id) { 1756 $moveitem->position = $pos; 1757 feedback_update_item($moveitem); 1758 continue; 1759 } 1760 $item->position = $index; 1761 feedback_update_item($item); 1762 $index++; 1763 } 1764 return true; 1765 } 1766 return false; 1767 } 1768 1769 /** 1770 * prints the given item as a preview. 1771 * each item-class has an own print_item_preview function implemented. 1772 * 1773 * @global object 1774 * @param object $item the item what we want to print out 1775 * @return void 1776 */ 1777 function feedback_print_item_preview($item) { 1778 global $CFG; 1779 if ($item->typ == 'pagebreak') { 1780 return; 1781 } 1782 //get the instance of the item-class 1783 $itemobj = feedback_get_item_class($item->typ); 1784 $itemobj->print_item_preview($item); 1785 } 1786 1787 /** 1788 * prints the given item in the completion form. 1789 * each item-class has an own print_item_complete function implemented. 1790 * 1791 * @param object $item the item what we want to print out 1792 * @param mixed $value the value 1793 * @param boolean $highlightrequire if this set true and the value are false on completing so the item will be highlighted 1794 * @return void 1795 */ 1796 function feedback_print_item_complete($item, $value = false, $highlightrequire = false) { 1797 global $CFG; 1798 if ($item->typ == 'pagebreak') { 1799 return; 1800 } 1801 1802 //get the instance of the item-class 1803 $itemobj = feedback_get_item_class($item->typ); 1804 $itemobj->print_item_complete($item, $value, $highlightrequire); 1805 } 1806 1807 /** 1808 * prints the given item in the show entries page. 1809 * each item-class has an own print_item_show_value function implemented. 1810 * 1811 * @param object $item the item what we want to print out 1812 * @param mixed $value 1813 * @return void 1814 */ 1815 function feedback_print_item_show_value($item, $value = false) { 1816 global $CFG; 1817 if ($item->typ == 'pagebreak') { 1818 return; 1819 } 1820 1821 //get the instance of the item-class 1822 $itemobj = feedback_get_item_class($item->typ); 1823 $itemobj->print_item_show_value($item, $value); 1824 } 1825 1826 /** 1827 * if the user completes a feedback and there is a pagebreak so the values are saved temporary. 1828 * the values are not saved permanently until the user click on save button 1829 * 1830 * @global object 1831 * @param object $feedbackcompleted 1832 * @return object temporary saved completed-record 1833 */ 1834 function feedback_set_tmp_values($feedbackcompleted) { 1835 global $DB; 1836 1837 //first we create a completedtmp 1838 $tmpcpl = new stdClass(); 1839 foreach ($feedbackcompleted as $key => $value) { 1840 $tmpcpl->{$key} = $value; 1841 } 1842 unset($tmpcpl->id); 1843 $tmpcpl->timemodified = time(); 1844 $tmpcpl->id = $DB->insert_record('feedback_completedtmp', $tmpcpl); 1845 //get all values of original-completed 1846 if (!$values = $DB->get_records('feedback_value', array('completed'=>$feedbackcompleted->id))) { 1847 return; 1848 } 1849 foreach ($values as $value) { 1850 unset($value->id); 1851 $value->completed = $tmpcpl->id; 1852 $DB->insert_record('feedback_valuetmp', $value); 1853 } 1854 return $tmpcpl; 1855 } 1856 1857 /** 1858 * this saves the temporary saved values permanently 1859 * 1860 * @global object 1861 * @param object $feedbackcompletedtmp the temporary completed 1862 * @param object $feedbackcompleted the target completed 1863 * @param int $userid 1864 * @return int the id of the completed 1865 */ 1866 function feedback_save_tmp_values($feedbackcompletedtmp, $feedbackcompleted, $userid) { 1867 global $DB; 1868 1869 $tmpcplid = $feedbackcompletedtmp->id; 1870 if ($feedbackcompleted) { 1871 //first drop all existing values 1872 $DB->delete_records('feedback_value', array('completed'=>$feedbackcompleted->id)); 1873 //update the current completed 1874 $feedbackcompleted->timemodified = time(); 1875 $DB->update_record('feedback_completed', $feedbackcompleted); 1876 } else { 1877 $feedbackcompleted = clone($feedbackcompletedtmp); 1878 $feedbackcompleted->id = ''; 1879 $feedbackcompleted->userid = $userid; 1880 $feedbackcompleted->timemodified = time(); 1881 $feedbackcompleted->id = $DB->insert_record('feedback_completed', $feedbackcompleted); 1882 } 1883 1884 //save all the new values from feedback_valuetmp 1885 //get all values of tmp-completed 1886 $params = array('completed'=>$feedbackcompletedtmp->id); 1887 if (!$values = $DB->get_records('feedback_valuetmp', $params)) { 1888 return false; 1889 } 1890 foreach ($values as $value) { 1891 //check if there are depend items 1892 $item = $DB->get_record('feedback_item', array('id'=>$value->item)); 1893 if ($item->dependitem > 0) { 1894 $check = feedback_compare_item_value($tmpcplid, 1895 $item->dependitem, 1896 $item->dependvalue, 1897 true); 1898 } else { 1899 $check = true; 1900 } 1901 if ($check) { 1902 unset($value->id); 1903 $value->completed = $feedbackcompleted->id; 1904 $DB->insert_record('feedback_value', $value); 1905 } 1906 } 1907 //drop all the tmpvalues 1908 $DB->delete_records('feedback_valuetmp', array('completed'=>$tmpcplid)); 1909 $DB->delete_records('feedback_completedtmp', array('id'=>$tmpcplid)); 1910 1911 // Trigger event for the delete action we performed. 1912 $cm = get_coursemodule_from_instance('feedback', $feedbackcompleted->feedback); 1913 $event = \mod_feedback\event\response_submitted::create(array( 1914 'relateduserid' => $userid, 1915 'objectid' => $feedbackcompleted->id, 1916 'context' => context_module::instance($cm->id), 1917 'anonymous' => ($feedbackcompleted->anonymous_response == FEEDBACK_ANONYMOUS_YES), 1918 'other' => array( 1919 'cmid' => $cm->id, 1920 'instanceid' => $feedbackcompleted->feedback, 1921 'anonymous' => $feedbackcompleted->anonymous_response // Deprecated. 1922 ) 1923 )); 1924 1925 $event->add_record_snapshot('feedback_completed', $feedbackcompleted); 1926 1927 $event->trigger(); 1928 return $feedbackcompleted->id; 1929 1930 } 1931 1932 /** 1933 * deletes the given temporary completed and all related temporary values 1934 * 1935 * @global object 1936 * @param int $tmpcplid 1937 * @return void 1938 */ 1939 function feedback_delete_completedtmp($tmpcplid) { 1940 global $DB; 1941 1942 $DB->delete_records('feedback_valuetmp', array('completed'=>$tmpcplid)); 1943 $DB->delete_records('feedback_completedtmp', array('id'=>$tmpcplid)); 1944 } 1945 1946 //////////////////////////////////////////////// 1947 //////////////////////////////////////////////// 1948 //////////////////////////////////////////////// 1949 //functions to handle the pagebreaks 1950 //////////////////////////////////////////////// 1951 1952 /** 1953 * this creates a pagebreak. 1954 * a pagebreak is a special kind of item 1955 * 1956 * @global object 1957 * @param int $feedbackid 1958 * @return mixed false if there already is a pagebreak on last position or the id of the pagebreak-item 1959 */ 1960 function feedback_create_pagebreak($feedbackid) { 1961 global $DB; 1962 1963 //check if there already is a pagebreak on the last position 1964 $lastposition = $DB->count_records('feedback_item', array('feedback'=>$feedbackid)); 1965 if ($lastposition == feedback_get_last_break_position($feedbackid)) { 1966 return false; 1967 } 1968 1969 $item = new stdClass(); 1970 $item->feedback = $feedbackid; 1971 1972 $item->template=0; 1973 1974 $item->name = ''; 1975 1976 $item->presentation = ''; 1977 $item->hasvalue = 0; 1978 1979 $item->typ = 'pagebreak'; 1980 $item->position = $lastposition + 1; 1981 1982 $item->required=0; 1983 1984 return $DB->insert_record('feedback_item', $item); 1985 } 1986 1987 /** 1988 * get all positions of pagebreaks in the given feedback 1989 * 1990 * @global object 1991 * @param int $feedbackid 1992 * @return array all ordered pagebreak positions 1993 */ 1994 function feedback_get_all_break_positions($feedbackid) { 1995 global $DB; 1996 1997 $params = array('typ'=>'pagebreak', 'feedback'=>$feedbackid); 1998 $allbreaks = $DB->get_records_menu('feedback_item', $params, 'position', 'id, position'); 1999 if (!$allbreaks) { 2000 return false; 2001 } 2002 return array_values($allbreaks); 2003 } 2004 2005 /** 2006 * get the position of the last pagebreak 2007 * 2008 * @param int $feedbackid 2009 * @return int the position of the last pagebreak 2010 */ 2011 function feedback_get_last_break_position($feedbackid) { 2012 if (!$allbreaks = feedback_get_all_break_positions($feedbackid)) { 2013 return false; 2014 } 2015 return $allbreaks[count($allbreaks) - 1]; 2016 } 2017 2018 /** 2019 * this returns the position where the user can continue the completing. 2020 * 2021 * @global object 2022 * @global object 2023 * @global object 2024 * @param int $feedbackid 2025 * @param int $courseid 2026 * @param string $guestid this id will be saved temporary and is unique 2027 * @return int the position to continue 2028 */ 2029 function feedback_get_page_to_continue($feedbackid, $courseid = false, $guestid = false) { 2030 global $CFG, $USER, $DB; 2031 2032 //is there any break? 2033 2034 if (!$allbreaks = feedback_get_all_break_positions($feedbackid)) { 2035 return false; 2036 } 2037 2038 $params = array(); 2039 if ($courseid) { 2040 $courseselect = "AND fv.course_id = :courseid"; 2041 $params['courseid'] = $courseid; 2042 } else { 2043 $courseselect = ''; 2044 } 2045 2046 if ($guestid) { 2047 $userselect = "AND fc.guestid = :guestid"; 2048 $usergroup = "GROUP BY fc.guestid"; 2049 $params['guestid'] = $guestid; 2050 } else { 2051 $userselect = "AND fc.userid = :userid"; 2052 $usergroup = "GROUP BY fc.userid"; 2053 $params['userid'] = $USER->id; 2054 } 2055 2056 $sql = "SELECT MAX(fi.position) 2057 FROM {feedback_completedtmp} fc, {feedback_valuetmp} fv, {feedback_item} fi 2058 WHERE fc.id = fv.completed 2059 $userselect 2060 AND fc.feedback = :feedbackid 2061 $courseselect 2062 AND fi.id = fv.item 2063 $usergroup"; 2064 $params['feedbackid'] = $feedbackid; 2065 2066 $lastpos = $DB->get_field_sql($sql, $params); 2067 2068 //the index of found pagebreak is the searched pagenumber 2069 foreach ($allbreaks as $pagenr => $br) { 2070 if ($lastpos < $br) { 2071 return $pagenr; 2072 } 2073 } 2074 return count($allbreaks); 2075 } 2076 2077 //////////////////////////////////////////////// 2078 //////////////////////////////////////////////// 2079 //////////////////////////////////////////////// 2080 //functions to handle the values 2081 //////////////////////////////////////////////// 2082 2083 /** 2084 * cleans the userinput while submitting the form. 2085 * 2086 * @param mixed $value 2087 * @return mixed 2088 */ 2089 function feedback_clean_input_value($item, $value) { 2090 $itemobj = feedback_get_item_class($item->typ); 2091 return $itemobj->clean_input_value($value); 2092 } 2093 2094 /** 2095 * this saves the values of an completed. 2096 * if the param $tmp is set true so the values are saved temporary in table feedback_valuetmp. 2097 * if there is already a completed and the userid is set so the values are updated. 2098 * on all other things new value records will be created. 2099 * 2100 * @global object 2101 * @param int $userid 2102 * @param boolean $tmp 2103 * @return mixed false on error or the completeid 2104 */ 2105 function feedback_save_values($usrid, $tmp = false) { 2106 global $DB; 2107 2108 $completedid = optional_param('completedid', 0, PARAM_INT); 2109 2110 $tmpstr = $tmp ? 'tmp' : ''; 2111 $time = time(); 2112 $timemodified = mktime(0, 0, 0, date('m', $time), date('d', $time), date('Y', $time)); 2113 2114 if ($usrid == 0) { 2115 return feedback_create_values($usrid, $timemodified, $tmp); 2116 } 2117 $completed = $DB->get_record('feedback_completed'.$tmpstr, array('id'=>$completedid)); 2118 if (!$completed) { 2119 return feedback_create_values($usrid, $timemodified, $tmp); 2120 } else { 2121 $completed->timemodified = $timemodified; 2122 return feedback_update_values($completed, $tmp); 2123 } 2124 } 2125 2126 /** 2127 * this saves the values from anonymous user such as guest on the main-site 2128 * 2129 * @global object 2130 * @param string $guestid the unique guestidentifier 2131 * @return mixed false on error or the completeid 2132 */ 2133 function feedback_save_guest_values($guestid) { 2134 global $DB; 2135 2136 $completedid = optional_param('completedid', false, PARAM_INT); 2137 2138 $timemodified = time(); 2139 if (!$completed = $DB->get_record('feedback_completedtmp', array('id'=>$completedid))) { 2140 return feedback_create_values(0, $timemodified, true, $guestid); 2141 } else { 2142 $completed->timemodified = $timemodified; 2143 return feedback_update_values($completed, true); 2144 } 2145 } 2146 2147 /** 2148 * get the value from the given item related to the given completed. 2149 * the value can come as temporary or as permanently value. the deciding is done by $tmp 2150 * 2151 * @global object 2152 * @param int $completeid 2153 * @param int $itemid 2154 * @param boolean $tmp 2155 * @return mixed the value, the type depends on plugin-definition 2156 */ 2157 function feedback_get_item_value($completedid, $itemid, $tmp = false) { 2158 global $DB; 2159 2160 $tmpstr = $tmp ? 'tmp' : ''; 2161 $params = array('completed'=>$completedid, 'item'=>$itemid); 2162 return $DB->get_field('feedback_value'.$tmpstr, 'value', $params); 2163 } 2164 2165 /** 2166 * compares the value of the itemid related to the completedid with the dependvalue. 2167 * this is used if a depend item is set. 2168 * the value can come as temporary or as permanently value. the deciding is done by $tmp. 2169 * 2170 * @global object 2171 * @global object 2172 * @param int $completeid 2173 * @param int $itemid 2174 * @param mixed $dependvalue 2175 * @param boolean $tmp 2176 * @return bool 2177 */ 2178 function feedback_compare_item_value($completedid, $itemid, $dependvalue, $tmp = false) { 2179 global $DB, $CFG; 2180 2181 $dbvalue = feedback_get_item_value($completedid, $itemid, $tmp); 2182 2183 //get the class of the given item-typ 2184 $item = $DB->get_record('feedback_item', array('id'=>$itemid)); 2185 2186 //get the instance of the item-class 2187 $itemobj = feedback_get_item_class($item->typ); 2188 return $itemobj->compare_value($item, $dbvalue, $dependvalue); //true or false 2189 } 2190 2191 /** 2192 * this function checks the correctness of values. 2193 * the rules for this are implemented in the class of each item. 2194 * it can be the required attribute or the value self e.g. numeric. 2195 * the params first/lastitem are given to determine the visible range between pagebreaks. 2196 * 2197 * @global object 2198 * @param int $firstitem the position of firstitem for checking 2199 * @param int $lastitem the position of lastitem for checking 2200 * @return boolean 2201 */ 2202 function feedback_check_values($firstitem, $lastitem) { 2203 global $DB, $CFG; 2204 2205 $feedbackid = optional_param('feedbackid', 0, PARAM_INT); 2206 2207 //get all items between the first- and lastitem 2208 $select = "feedback = ? 2209 AND position >= ? 2210 AND position <= ? 2211 AND hasvalue = 1"; 2212 $params = array($feedbackid, $firstitem, $lastitem); 2213 if (!$feedbackitems = $DB->get_records_select('feedback_item', $select, $params)) { 2214 //if no values are given so no values can be wrong ;-) 2215 return true; 2216 } 2217 2218 foreach ($feedbackitems as $item) { 2219 //get the instance of the item-class 2220 $itemobj = feedback_get_item_class($item->typ); 2221 2222 //the name of the input field of the completeform is given in a special form: 2223 //<item-typ>_<item-id> eg. numeric_234 2224 //this is the key to get the value for the correct item 2225 $formvalname = $item->typ . '_' . $item->id; 2226 2227 if ($itemobj->value_is_array()) { 2228 //get the raw value here. It is cleaned after that by the object itself 2229 $value = optional_param_array($formvalname, null, PARAM_RAW); 2230 } else { 2231 //get the raw value here. It is cleaned after that by the object itself 2232 $value = optional_param($formvalname, null, PARAM_RAW); 2233 } 2234 $value = $itemobj->clean_input_value($value); 2235 2236 // If the item is not visible due to its dependency so it shouldn't be required. 2237 // Many thanks to Pau Ferrer Ocaña. 2238 if ($item->dependitem > 0 AND $item->required == 1) { 2239 $comparevalue = false; 2240 if ($feedbackcompletedtmp = feedback_get_current_completed($item->feedback, true)) { 2241 $comparevalue = feedback_compare_item_value($feedbackcompletedtmp->id, 2242 $item->dependitem, 2243 $item->dependvalue, 2244 true); 2245 } 2246 2247 if (!$comparevalue) { 2248 $item->required = 0; // Override the required property. 2249 } 2250 } 2251 2252 //check if the value is set 2253 if (is_null($value) AND $item->required == 1) { 2254 return false; 2255 } 2256 2257 //now we let check the value by the item-class 2258 if (!$itemobj->check_value($value, $item)) { 2259 return false; 2260 } 2261 } 2262 //if no wrong values so we can return true 2263 return true; 2264 } 2265 2266 /** 2267 * this function create a complete-record and the related value-records. 2268 * depending on the $tmp (true/false) the values are saved temporary or permanently 2269 * 2270 * @global object 2271 * @param int $userid 2272 * @param int $timemodified 2273 * @param boolean $tmp 2274 * @param string $guestid a unique identifier to save temporary data 2275 * @return mixed false on error or the completedid 2276 */ 2277 function feedback_create_values($usrid, $timemodified, $tmp = false, $guestid = false) { 2278 global $DB; 2279 2280 $feedbackid = optional_param('feedbackid', false, PARAM_INT); 2281 $anonymous_response = optional_param('anonymous_response', false, PARAM_INT); 2282 $courseid = optional_param('courseid', false, PARAM_INT); 2283 2284 $tmpstr = $tmp ? 'tmp' : ''; 2285 //first we create a new completed record 2286 $completed = new stdClass(); 2287 $completed->feedback = $feedbackid; 2288 $completed->userid = $usrid; 2289 $completed->guestid = $guestid; 2290 $completed->timemodified = $timemodified; 2291 $completed->anonymous_response = $anonymous_response; 2292 2293 $completedid = $DB->insert_record('feedback_completed'.$tmpstr, $completed); 2294 2295 $completed = $DB->get_record('feedback_completed'.$tmpstr, array('id'=>$completedid)); 2296 2297 //the keys are in the form like abc_xxx 2298 //with explode we make an array with(abc, xxx) and (abc=typ und xxx=itemnr) 2299 2300 //get the items of the feedback 2301 if (!$allitems = $DB->get_records('feedback_item', array('feedback'=>$completed->feedback))) { 2302 return false; 2303 } 2304 foreach ($allitems as $item) { 2305 if (!$item->hasvalue) { 2306 continue; 2307 } 2308 //get the class of item-typ 2309 $itemobj = feedback_get_item_class($item->typ); 2310 2311 $keyname = $item->typ.'_'.$item->id; 2312 2313 if ($itemobj->value_is_array()) { 2314 $itemvalue = optional_param_array($keyname, null, $itemobj->value_type()); 2315 } else { 2316 $itemvalue = optional_param($keyname, null, $itemobj->value_type()); 2317 } 2318 2319 if (is_null($itemvalue)) { 2320 continue; 2321 } 2322 2323 $value = new stdClass(); 2324 $value->item = $item->id; 2325 $value->completed = $completed->id; 2326 $value->course_id = $courseid; 2327 2328 //the kind of values can be absolutely different 2329 //so we run create_value directly by the item-class 2330 $value->value = $itemobj->create_value($itemvalue); 2331 $DB->insert_record('feedback_value'.$tmpstr, $value); 2332 } 2333 return $completed->id; 2334 } 2335 2336 /** 2337 * this function updates a complete-record and the related value-records. 2338 * depending on the $tmp (true/false) the values are saved temporary or permanently 2339 * 2340 * @global object 2341 * @param object $completed 2342 * @param boolean $tmp 2343 * @return int the completedid 2344 */ 2345 function feedback_update_values($completed, $tmp = false) { 2346 global $DB; 2347 2348 $courseid = optional_param('courseid', false, PARAM_INT); 2349 $tmpstr = $tmp ? 'tmp' : ''; 2350 2351 $DB->update_record('feedback_completed'.$tmpstr, $completed); 2352 //get the values of this completed 2353 $values = $DB->get_records('feedback_value'.$tmpstr, array('completed'=>$completed->id)); 2354 2355 //get the items of the feedback 2356 if (!$allitems = $DB->get_records('feedback_item', array('feedback'=>$completed->feedback))) { 2357 return false; 2358 } 2359 foreach ($allitems as $item) { 2360 if (!$item->hasvalue) { 2361 continue; 2362 } 2363 //get the class of item-typ 2364 $itemobj = feedback_get_item_class($item->typ); 2365 2366 $keyname = $item->typ.'_'.$item->id; 2367 2368 if ($itemobj->value_is_array()) { 2369 $itemvalue = optional_param_array($keyname, null, $itemobj->value_type()); 2370 } else { 2371 $itemvalue = optional_param($keyname, null, $itemobj->value_type()); 2372 } 2373 2374 //is the itemvalue set (could be a subset of items because pagebreak)? 2375 if (is_null($itemvalue)) { 2376 continue; 2377 } 2378 2379 $newvalue = new stdClass(); 2380 $newvalue->item = $item->id; 2381 $newvalue->completed = $completed->id; 2382 $newvalue->course_id = $courseid; 2383 2384 //the kind of values can be absolutely different 2385 //so we run create_value directly by the item-class 2386 $newvalue->value = $itemobj->create_value($itemvalue); 2387 2388 //check, if we have to create or update the value 2389 $exist = false; 2390 foreach ($values as $value) { 2391 if ($value->item == $newvalue->item) { 2392 $newvalue->id = $value->id; 2393 $exist = true; 2394 break; 2395 } 2396 } 2397 if ($exist) { 2398 $DB->update_record('feedback_value'.$tmpstr, $newvalue); 2399 } else { 2400 $DB->insert_record('feedback_value'.$tmpstr, $newvalue); 2401 } 2402 } 2403 2404 return $completed->id; 2405 } 2406 2407 /** 2408 * get the values of an item depending on the given groupid. 2409 * if the feedback is anonymous so the values are shuffled 2410 * 2411 * @global object 2412 * @global object 2413 * @param object $item 2414 * @param int $groupid 2415 * @param int $courseid 2416 * @param bool $ignore_empty if this is set true so empty values are not delivered 2417 * @return array the value-records 2418 */ 2419 function feedback_get_group_values($item, 2420 $groupid = false, 2421 $courseid = false, 2422 $ignore_empty = false) { 2423 2424 global $CFG, $DB; 2425 2426 //if the groupid is given? 2427 if (intval($groupid) > 0) { 2428 $params = array(); 2429 if ($ignore_empty) { 2430 $value = $DB->sql_compare_text('fbv.value'); 2431 $ignore_empty_select = "AND $value != :emptyvalue AND $value != :zerovalue"; 2432 $params += array('emptyvalue' => '', 'zerovalue' => '0'); 2433 } else { 2434 $ignore_empty_select = ""; 2435 } 2436 2437 $query = 'SELECT fbv . * 2438 FROM {feedback_value} fbv, {feedback_completed} fbc, {groups_members} gm 2439 WHERE fbv.item = :itemid 2440 AND fbv.completed = fbc.id 2441 AND fbc.userid = gm.userid 2442 '.$ignore_empty_select.' 2443 AND gm.groupid = :groupid 2444 ORDER BY fbc.timemodified'; 2445 $params += array('itemid' => $item->id, 'groupid' => $groupid); 2446 $values = $DB->get_records_sql($query, $params); 2447 2448 } else { 2449 $params = array(); 2450 if ($ignore_empty) { 2451 $value = $DB->sql_compare_text('value'); 2452 $ignore_empty_select = "AND $value != :emptyvalue AND $value != :zerovalue"; 2453 $params += array('emptyvalue' => '', 'zerovalue' => '0'); 2454 } else { 2455 $ignore_empty_select = ""; 2456 } 2457 2458 if ($courseid) { 2459 $select = "item = :itemid AND course_id = :courseid ".$ignore_empty_select; 2460 $params += array('itemid' => $item->id, 'courseid' => $courseid); 2461 $values = $DB->get_records_select('feedback_value', $select, $params); 2462 } else { 2463 $select = "item = :itemid ".$ignore_empty_select; 2464 $params += array('itemid' => $item->id); 2465 $values = $DB->get_records_select('feedback_value', $select, $params); 2466 } 2467 } 2468 $params = array('id'=>$item->feedback); 2469 if ($DB->get_field('feedback', 'anonymous', $params) == FEEDBACK_ANONYMOUS_YES) { 2470 if (is_array($values)) { 2471 shuffle($values); 2472 } 2473 } 2474 return $values; 2475 } 2476 2477 /** 2478 * check for multiple_submit = false. 2479 * if the feedback is global so the courseid must be given 2480 * 2481 * @global object 2482 * @global object 2483 * @param int $feedbackid 2484 * @param int $courseid 2485 * @return boolean true if the feedback already is submitted otherwise false 2486 */ 2487 function feedback_is_already_submitted($feedbackid, $courseid = false) { 2488 global $USER, $DB; 2489 2490 $params = array('userid'=>$USER->id, 'feedback'=>$feedbackid); 2491 if (!$trackings = $DB->get_records_menu('feedback_tracking', $params, '', 'id, completed')) { 2492 return false; 2493 } 2494 2495 if ($courseid) { 2496 $select = 'completed IN ('.implode(',', $trackings).') AND course_id = ?'; 2497 if (!$values = $DB->get_records_select('feedback_value', $select, array($courseid))) { 2498 return false; 2499 } 2500 } 2501 2502 return true; 2503 } 2504 2505 /** 2506 * if the completion of a feedback will be continued eg. 2507 * by pagebreak or by multiple submit so the complete must be found. 2508 * if the param $tmp is set true so all things are related to temporary completeds 2509 * 2510 * @global object 2511 * @global object 2512 * @global object 2513 * @param int $feedbackid 2514 * @param boolean $tmp 2515 * @param int $courseid 2516 * @param string $guestid 2517 * @return int the id of the found completed 2518 */ 2519 function feedback_get_current_completed($feedbackid, 2520 $tmp = false, 2521 $courseid = false, 2522 $guestid = false) { 2523 2524 global $USER, $CFG, $DB; 2525 2526 $tmpstr = $tmp ? 'tmp' : ''; 2527 2528 if (!$courseid) { 2529 if ($guestid) { 2530 $params = array('feedback'=>$feedbackid, 'guestid'=>$guestid); 2531 return $DB->get_record('feedback_completed'.$tmpstr, $params); 2532 } else { 2533 $params = array('feedback'=>$feedbackid, 'userid'=>$USER->id); 2534 return $DB->get_record('feedback_completed'.$tmpstr, $params); 2535 } 2536 } 2537 2538 $params = array(); 2539 2540 if ($guestid) { 2541 $userselect = "AND fc.guestid = :guestid"; 2542 $params['guestid'] = $guestid; 2543 } else { 2544 $userselect = "AND fc.userid = :userid"; 2545 $params['userid'] = $USER->id; 2546 } 2547 //if courseid is set the feedback is global. 2548 //there can be more than one completed on one feedback 2549 $sql = "SELECT DISTINCT fc.* 2550 FROM {feedback_value{$tmpstr}} fv, {feedback_completed{$tmpstr}} fc 2551 WHERE fv.course_id = :courseid 2552 AND fv.completed = fc.id 2553 $userselect 2554 AND fc.feedback = :feedbackid"; 2555 $params['courseid'] = intval($courseid); 2556 $params['feedbackid'] = $feedbackid; 2557 2558 if (!$sqlresult = $DB->get_records_sql($sql, $params)) { 2559 return false; 2560 } 2561 foreach ($sqlresult as $r) { 2562 return $DB->get_record('feedback_completed'.$tmpstr, array('id'=>$r->id)); 2563 } 2564 } 2565 2566 /** 2567 * get the completeds depending on the given groupid. 2568 * 2569 * @global object 2570 * @global object 2571 * @param object $feedback 2572 * @param int $groupid 2573 * @param int $courseid 2574 * @return mixed array of found completeds otherwise false 2575 */ 2576 function feedback_get_completeds_group($feedback, $groupid = false, $courseid = false) { 2577 global $CFG, $DB; 2578 2579 if (intval($groupid) > 0) { 2580 $query = "SELECT fbc.* 2581 FROM {feedback_completed} fbc, {groups_members} gm 2582 WHERE fbc.feedback = ? 2583 AND gm.groupid = ? 2584 AND fbc.userid = gm.userid"; 2585 if ($values = $DB->get_records_sql($query, array($feedback->id, $groupid))) { 2586 return $values; 2587 } else { 2588 return false; 2589 } 2590 } else { 2591 if ($courseid) { 2592 $query = "SELECT DISTINCT fbc.* 2593 FROM {feedback_completed} fbc, {feedback_value} fbv 2594 WHERE fbc.id = fbv.completed 2595 AND fbc.feedback = ? 2596 AND fbv.course_id = ? 2597 ORDER BY random_response"; 2598 if ($values = $DB->get_records_sql($query, array($feedback->id, $courseid))) { 2599 return $values; 2600 } else { 2601 return false; 2602 } 2603 } else { 2604 if ($values = $DB->get_records('feedback_completed', array('feedback'=>$feedback->id))) { 2605 return $values; 2606 } else { 2607 return false; 2608 } 2609 } 2610 } 2611 } 2612 2613 /** 2614 * get the count of completeds depending on the given groupid. 2615 * 2616 * @global object 2617 * @global object 2618 * @param object $feedback 2619 * @param int $groupid 2620 * @param int $courseid 2621 * @return mixed count of completeds or false 2622 */ 2623 function feedback_get_completeds_group_count($feedback, $groupid = false, $courseid = false) { 2624 global $CFG, $DB; 2625 2626 if ($courseid > 0 AND !$groupid <= 0) { 2627 $sql = "SELECT id, COUNT(item) AS ci 2628 FROM {feedback_value} 2629 WHERE course_id = ? 2630 GROUP BY item ORDER BY ci DESC"; 2631 if ($foundrecs = $DB->get_records_sql($sql, array($courseid))) { 2632 $foundrecs = array_values($foundrecs); 2633 return $foundrecs[0]->ci; 2634 } 2635 return false; 2636 } 2637 if ($values = feedback_get_completeds_group($feedback, $groupid)) { 2638 return count($values); 2639 } else { 2640 return false; 2641 } 2642 } 2643 2644 /** 2645 * deletes all completed-recordsets from a feedback. 2646 * all related data such as values also will be deleted 2647 * 2648 * @global object 2649 * @param int $feedbackid 2650 * @return void 2651 */ 2652 function feedback_delete_all_completeds($feedbackid) { 2653 global $DB; 2654 2655 if (!$completeds = $DB->get_records('feedback_completed', array('feedback'=>$feedbackid))) { 2656 return; 2657 } 2658 foreach ($completeds as $completed) { 2659 feedback_delete_completed($completed->id); 2660 } 2661 } 2662 2663 /** 2664 * deletes a completed given by completedid. 2665 * all related data such values or tracking data also will be deleted 2666 * 2667 * @global object 2668 * @param int $completedid 2669 * @return boolean 2670 */ 2671 function feedback_delete_completed($completedid) { 2672 global $DB, $CFG; 2673 require_once($CFG->libdir.'/completionlib.php'); 2674 2675 if (!$completed = $DB->get_record('feedback_completed', array('id'=>$completedid))) { 2676 return false; 2677 } 2678 2679 if (!$feedback = $DB->get_record('feedback', array('id'=>$completed->feedback))) { 2680 return false; 2681 } 2682 2683 if (!$course = $DB->get_record('course', array('id'=>$feedback->course))) { 2684 return false; 2685 } 2686 2687 if (!$cm = get_coursemodule_from_instance('feedback', $feedback->id)) { 2688 return false; 2689 } 2690 2691 //first we delete all related values 2692 $DB->delete_records('feedback_value', array('completed'=>$completed->id)); 2693 2694 //now we delete all tracking data 2695 $params = array('completed'=>$completed->id, 'feedback'=>$completed->feedback); 2696 if ($tracking = $DB->get_record('feedback_tracking', $params)) { 2697 $DB->delete_records('feedback_tracking', array('completed'=>$completed->id)); 2698 } 2699 2700 // Update completion state 2701 $completion = new completion_info($course); 2702 if ($completion->is_enabled($cm) && $feedback->completionsubmit) { 2703 $completion->update_state($cm, COMPLETION_INCOMPLETE, $completed->userid); 2704 } 2705 // Last we delete the completed-record. 2706 $return = $DB->delete_records('feedback_completed', array('id'=>$completed->id)); 2707 2708 // Trigger event for the delete action we performed. 2709 $event = \mod_feedback\event\response_deleted::create(array( 2710 'relateduserid' => $completed->userid, 2711 'objectid' => $completedid, 2712 'courseid' => $course->id, 2713 'context' => context_module::instance($cm->id), 2714 'anonymous' => ($completed->anonymous_response == FEEDBACK_ANONYMOUS_YES), 2715 'other' => array( 2716 'cmid' => $cm->id, 2717 'instanceid' => $feedback->id, 2718 'anonymous' => $completed->anonymous_response) // Deprecated. 2719 )); 2720 2721 $event->add_record_snapshot('feedback_completed', $completed); 2722 $event->add_record_snapshot('course', $course); 2723 $event->add_record_snapshot('feedback', $feedback); 2724 2725 $event->trigger(); 2726 2727 return $return; 2728 } 2729 2730 //////////////////////////////////////////////// 2731 //////////////////////////////////////////////// 2732 //////////////////////////////////////////////// 2733 //functions to handle sitecourse mapping 2734 //////////////////////////////////////////////// 2735 2736 /** 2737 * checks if the course and the feedback is in the table feedback_sitecourse_map. 2738 * 2739 * @global object 2740 * @param int $feedbackid 2741 * @param int $courseid 2742 * @return int the count of records 2743 */ 2744 function feedback_is_course_in_sitecourse_map($feedbackid, $courseid) { 2745 global $DB; 2746 $params = array('feedbackid'=>$feedbackid, 'courseid'=>$courseid); 2747 return $DB->count_records('feedback_sitecourse_map', $params); 2748 } 2749 2750 /** 2751 * checks if the feedback is in the table feedback_sitecourse_map. 2752 * 2753 * @global object 2754 * @param int $feedbackid 2755 * @return boolean 2756 */ 2757 function feedback_is_feedback_in_sitecourse_map($feedbackid) { 2758 global $DB; 2759 return $DB->record_exists('feedback_sitecourse_map', array('feedbackid'=>$feedbackid)); 2760 } 2761 2762 /** 2763 * gets the feedbacks from table feedback_sitecourse_map. 2764 * this is used to show the global feedbacks on the feedback block 2765 * all feedbacks with the following criteria will be selected:<br /> 2766 * 2767 * 1) all feedbacks which id are listed together with the courseid in sitecoursemap and<br /> 2768 * 2) all feedbacks which not are listed in sitecoursemap 2769 * 2770 * @global object 2771 * @param int $courseid 2772 * @return array the feedback-records 2773 */ 2774 function feedback_get_feedbacks_from_sitecourse_map($courseid) { 2775 global $DB; 2776 2777 //first get all feedbacks listed in sitecourse_map with named courseid 2778 $sql = "SELECT f.id AS id, 2779 cm.id AS cmid, 2780 f.name AS name, 2781 f.timeopen AS timeopen, 2782 f.timeclose AS timeclose 2783 FROM {feedback} f, {course_modules} cm, {feedback_sitecourse_map} sm, {modules} m 2784 WHERE f.id = cm.instance 2785 AND f.course = '".SITEID."' 2786 AND m.id = cm.module 2787 AND m.name = 'feedback' 2788 AND sm.courseid = ? 2789 AND sm.feedbackid = f.id"; 2790 2791 if (!$feedbacks1 = $DB->get_records_sql($sql, array($courseid))) { 2792 $feedbacks1 = array(); 2793 } 2794 2795 //second get all feedbacks not listed in sitecourse_map 2796 $feedbacks2 = array(); 2797 $sql = "SELECT f.id AS id, 2798 cm.id AS cmid, 2799 f.name AS name, 2800 f.timeopen AS timeopen, 2801 f.timeclose AS timeclose 2802 FROM {feedback} f, {course_modules} cm, {modules} m 2803 WHERE f.id = cm.instance 2804 AND f.course = '".SITEID."' 2805 AND m.id = cm.module 2806 AND m.name = 'feedback'"; 2807 if (!$allfeedbacks = $DB->get_records_sql($sql)) { 2808 $allfeedbacks = array(); 2809 } 2810 foreach ($allfeedbacks as $a) { 2811 if (!$DB->record_exists('feedback_sitecourse_map', array('feedbackid'=>$a->id))) { 2812 $feedbacks2[] = $a; 2813 } 2814 } 2815 2816 return array_merge($feedbacks1, $feedbacks2); 2817 2818 } 2819 2820 /** 2821 * gets the courses from table feedback_sitecourse_map. 2822 * 2823 * @global object 2824 * @param int $feedbackid 2825 * @return array the course-records 2826 */ 2827 function feedback_get_courses_from_sitecourse_map($feedbackid) { 2828 global $DB; 2829 2830 $sql = "SELECT f.id, f.courseid, c.fullname, c.shortname 2831 FROM {feedback_sitecourse_map} f, {course} c 2832 WHERE c.id = f.courseid 2833 AND f.feedbackid = ? 2834 ORDER BY c.fullname"; 2835 2836 return $DB->get_records_sql($sql, array($feedbackid)); 2837 2838 } 2839 2840 /** 2841 * removes non existing courses or feedbacks from sitecourse_map. 2842 * it shouldn't be called all too often 2843 * a good place for it could be the mapcourse.php or unmapcourse.php 2844 * 2845 * @global object 2846 * @return void 2847 */ 2848 function feedback_clean_up_sitecourse_map() { 2849 global $DB; 2850 2851 $maps = $DB->get_records('feedback_sitecourse_map'); 2852 foreach ($maps as $map) { 2853 if (!$DB->get_record('course', array('id'=>$map->courseid))) { 2854 $params = array('courseid'=>$map->courseid, 'feedbackid'=>$map->feedbackid); 2855 $DB->delete_records('feedback_sitecourse_map', $params); 2856 continue; 2857 } 2858 if (!$DB->get_record('feedback', array('id'=>$map->feedbackid))) { 2859 $params = array('courseid'=>$map->courseid, 'feedbackid'=>$map->feedbackid); 2860 $DB->delete_records('feedback_sitecourse_map', $params); 2861 continue; 2862 } 2863 2864 } 2865 } 2866 2867 //////////////////////////////////////////////// 2868 //////////////////////////////////////////////// 2869 //////////////////////////////////////////////// 2870 //not relatable functions 2871 //////////////////////////////////////////////// 2872 2873 /** 2874 * prints the option items of a selection-input item (dropdownlist). 2875 * @param int $startval the first value of the list 2876 * @param int $endval the last value of the list 2877 * @param int $selectval which item should be selected 2878 * @param int $interval the stepsize from the first to the last value 2879 * @return void 2880 */ 2881 function feedback_print_numeric_option_list($startval, $endval, $selectval = '', $interval = 1) { 2882 for ($i = $startval; $i <= $endval; $i += $interval) { 2883 if ($selectval == ($i)) { 2884 $selected = 'selected="selected"'; 2885 } else { 2886 $selected = ''; 2887 } 2888 echo '<option '.$selected.'>'.$i.'</option>'; 2889 } 2890 } 2891 2892 /** 2893 * sends an email to the teachers of the course where the given feedback is placed. 2894 * 2895 * @global object 2896 * @global object 2897 * @uses FEEDBACK_ANONYMOUS_NO 2898 * @uses FORMAT_PLAIN 2899 * @param object $cm the coursemodule-record 2900 * @param object $feedback 2901 * @param object $course 2902 * @param int $userid 2903 * @return void 2904 */ 2905 function feedback_send_email($cm, $feedback, $course, $userid) { 2906 global $CFG, $DB; 2907 2908 if ($feedback->email_notification == 0) { // No need to do anything 2909 return; 2910 } 2911 2912 $user = $DB->get_record('user', array('id'=>$userid)); 2913 2914 if (isset($cm->groupmode) && empty($course->groupmodeforce)) { 2915 $groupmode = $cm->groupmode; 2916 } else { 2917 $groupmode = $course->groupmode; 2918 } 2919 2920 if ($groupmode == SEPARATEGROUPS) { 2921 $groups = $DB->get_records_sql_menu("SELECT g.name, g.id 2922 FROM {groups} g, {groups_members} m 2923 WHERE g.courseid = ? 2924 AND g.id = m.groupid 2925 AND m.userid = ? 2926 ORDER BY name ASC", array($course->id, $userid)); 2927 $groups = array_values($groups); 2928 2929 $teachers = feedback_get_receivemail_users($cm->id, $groups); 2930 } else { 2931 $teachers = feedback_get_receivemail_users($cm->id); 2932 } 2933 2934 if ($teachers) { 2935 2936 $strfeedbacks = get_string('modulenameplural', 'feedback'); 2937 $strfeedback = get_string('modulename', 'feedback'); 2938 $strcompleted = get_string('completed', 'feedback'); 2939 2940 if ($feedback->anonymous == FEEDBACK_ANONYMOUS_NO) { 2941 $printusername = fullname($user); 2942 } else { 2943 $printusername = get_string('anonymous_user', 'feedback'); 2944 } 2945 2946 foreach ($teachers as $teacher) { 2947 $info = new stdClass(); 2948 $info->username = $printusername; 2949 $info->feedback = format_string($feedback->name, true); 2950 $info->url = $CFG->wwwroot.'/mod/feedback/show_entries.php?'. 2951 'id='.$cm->id.'&'. 2952 'userid='.$userid.'&'. 2953 'do_show=showentries'; 2954 2955 $postsubject = $strcompleted.': '.$info->username.' -> '.$feedback->name; 2956 $posttext = feedback_send_email_text($info, $course); 2957 2958 if ($teacher->mailformat == 1) { 2959 $posthtml = feedback_send_email_html($info, $course, $cm); 2960 } else { 2961 $posthtml = ''; 2962 } 2963 2964 if ($feedback->anonymous == FEEDBACK_ANONYMOUS_NO) { 2965 $eventdata = new stdClass(); 2966 $eventdata->name = 'submission'; 2967 $eventdata->component = 'mod_feedback'; 2968 $eventdata->userfrom = $user; 2969 $eventdata->userto = $teacher; 2970 $eventdata->subject = $postsubject; 2971 $eventdata->fullmessage = $posttext; 2972 $eventdata->fullmessageformat = FORMAT_PLAIN; 2973 $eventdata->fullmessagehtml = $posthtml; 2974 $eventdata->smallmessage = ''; 2975 message_send($eventdata); 2976 } else { 2977 $eventdata = new stdClass(); 2978 $eventdata->name = 'submission'; 2979 $eventdata->component = 'mod_feedback'; 2980 $eventdata->userfrom = $teacher; 2981 $eventdata->userto = $teacher; 2982 $eventdata->subject = $postsubject; 2983 $eventdata->fullmessage = $posttext; 2984 $eventdata->fullmessageformat = FORMAT_PLAIN; 2985 $eventdata->fullmessagehtml = $posthtml; 2986 $eventdata->smallmessage = ''; 2987 message_send($eventdata); 2988 } 2989 } 2990 } 2991 } 2992 2993 /** 2994 * sends an email to the teachers of the course where the given feedback is placed. 2995 * 2996 * @global object 2997 * @uses FORMAT_PLAIN 2998 * @param object $cm the coursemodule-record 2999 * @param object $feedback 3000 * @param object $course 3001 * @return void 3002 */ 3003 function feedback_send_email_anonym($cm, $feedback, $course) { 3004 global $CFG; 3005 3006 if ($feedback->email_notification == 0) { // No need to do anything 3007 return; 3008 } 3009 3010 $teachers = feedback_get_receivemail_users($cm->id); 3011 3012 if ($teachers) { 3013 3014 $strfeedbacks = get_string('modulenameplural', 'feedback'); 3015 $strfeedback = get_string('modulename', 'feedback'); 3016 $strcompleted = get_string('completed', 'feedback'); 3017 $printusername = get_string('anonymous_user', 'feedback'); 3018 3019 foreach ($teachers as $teacher) { 3020 $info = new stdClass(); 3021 $info->username = $printusername; 3022 $info->feedback = format_string($feedback->name, true); 3023 $info->url = $CFG->wwwroot.'/mod/feedback/show_entries_anonym.php?id='.$cm->id; 3024 3025 $postsubject = $strcompleted.': '.$info->username.' -> '.$feedback->name; 3026 $posttext = feedback_send_email_text($info, $course); 3027 3028 if ($teacher->mailformat == 1) { 3029 $posthtml = feedback_send_email_html($info, $course, $cm); 3030 } else { 3031 $posthtml = ''; 3032 } 3033 3034 $eventdata = new stdClass(); 3035 $eventdata->name = 'submission'; 3036 $eventdata->component = 'mod_feedback'; 3037 $eventdata->userfrom = $teacher; 3038 $eventdata->userto = $teacher; 3039 $eventdata->subject = $postsubject; 3040 $eventdata->fullmessage = $posttext; 3041 $eventdata->fullmessageformat = FORMAT_PLAIN; 3042 $eventdata->fullmessagehtml = $posthtml; 3043 $eventdata->smallmessage = ''; 3044 message_send($eventdata); 3045 } 3046 } 3047 } 3048 3049 /** 3050 * send the text-part of the email 3051 * 3052 * @param object $info includes some infos about the feedback you want to send 3053 * @param object $course 3054 * @return string the text you want to post 3055 */ 3056 function feedback_send_email_text($info, $course) { 3057 $coursecontext = context_course::instance($course->id); 3058 $courseshortname = format_string($course->shortname, true, array('context' => $coursecontext)); 3059 $posttext = $courseshortname.' -> '.get_string('modulenameplural', 'feedback').' -> '. 3060 $info->feedback."\n"; 3061 $posttext .= '---------------------------------------------------------------------'."\n"; 3062 $posttext .= get_string("emailteachermail", "feedback", $info)."\n"; 3063 $posttext .= '---------------------------------------------------------------------'."\n"; 3064 return $posttext; 3065 } 3066 3067 3068 /** 3069 * send the html-part of the email 3070 * 3071 * @global object 3072 * @param object $info includes some infos about the feedback you want to send 3073 * @param object $course 3074 * @return string the text you want to post 3075 */ 3076 function feedback_send_email_html($info, $course, $cm) { 3077 global $CFG; 3078 $coursecontext = context_course::instance($course->id); 3079 $courseshortname = format_string($course->shortname, true, array('context' => $coursecontext)); 3080 $course_url = $CFG->wwwroot.'/course/view.php?id='.$course->id; 3081 $feedback_all_url = $CFG->wwwroot.'/mod/feedback/index.php?id='.$course->id; 3082 $feedback_url = $CFG->wwwroot.'/mod/feedback/view.php?id='.$cm->id; 3083 3084 $posthtml = '<p><font face="sans-serif">'. 3085 '<a href="'.$course_url.'">'.$courseshortname.'</a> ->'. 3086 '<a href="'.$feedback_all_url.'">'.get_string('modulenameplural', 'feedback').'</a> ->'. 3087 '<a href="'.$feedback_url.'">'.$info->feedback.'</a></font></p>'; 3088 $posthtml .= '<hr /><font face="sans-serif">'; 3089 $posthtml .= '<p>'.get_string('emailteachermailhtml', 'feedback', $info).'</p>'; 3090 $posthtml .= '</font><hr />'; 3091 return $posthtml; 3092 } 3093 3094 /** 3095 * @param string $url 3096 * @return string 3097 */ 3098 function feedback_encode_target_url($url) { 3099 if (strpos($url, '?')) { 3100 list($part1, $part2) = explode('?', $url, 2); //maximal 2 parts 3101 return $part1 . '?' . htmlentities($part2); 3102 } else { 3103 return $url; 3104 } 3105 } 3106 3107 /** 3108 * Adds module specific settings to the settings block 3109 * 3110 * @param settings_navigation $settings The settings navigation object 3111 * @param navigation_node $feedbacknode The node to add module settings to 3112 */ 3113 function feedback_extend_settings_navigation(settings_navigation $settings, 3114 navigation_node $feedbacknode) { 3115 3116 global $PAGE, $DB; 3117 3118 if (!$context = context_module::instance($PAGE->cm->id, IGNORE_MISSING)) { 3119 print_error('badcontext'); 3120 } 3121 3122 if (has_capability('mod/feedback:edititems', $context)) { 3123 $questionnode = $feedbacknode->add(get_string('questions', 'feedback')); 3124 3125 $questionnode->add(get_string('edit_items', 'feedback'), 3126 new moodle_url('/mod/feedback/edit.php', 3127 array('id' => $PAGE->cm->id, 3128 'do_show' => 'edit'))); 3129 3130 $questionnode->add(get_string('export_questions', 'feedback'), 3131 new moodle_url('/mod/feedback/export.php', 3132 array('id' => $PAGE->cm->id, 3133 'action' => 'exportfile'))); 3134 3135 $questionnode->add(get_string('import_questions', 'feedback'), 3136 new moodle_url('/mod/feedback/import.php', 3137 array('id' => $PAGE->cm->id))); 3138 3139 $questionnode->add(get_string('templates', 'feedback'), 3140 new moodle_url('/mod/feedback/edit.php', 3141 array('id' => $PAGE->cm->id, 3142 'do_show' => 'templates'))); 3143 } 3144 3145 if (has_capability('mod/feedback:viewreports', $context)) { 3146 $feedback = $DB->get_record('feedback', array('id'=>$PAGE->cm->instance)); 3147 if ($feedback->course == SITEID) { 3148 $feedbacknode->add(get_string('analysis', 'feedback'), 3149 new moodle_url('/mod/feedback/analysis_course.php', 3150 array('id' => $PAGE->cm->id, 3151 'course' => $PAGE->course->id, 3152 'do_show' => 'analysis'))); 3153 } else { 3154 $feedbacknode->add(get_string('analysis', 'feedback'), 3155 new moodle_url('/mod/feedback/analysis.php', 3156 array('id' => $PAGE->cm->id, 3157 'course' => $PAGE->course->id, 3158 'do_show' => 'analysis'))); 3159 } 3160 3161 $feedbacknode->add(get_string('show_entries', 'feedback'), 3162 new moodle_url('/mod/feedback/show_entries.php', 3163 array('id' => $PAGE->cm->id, 3164 'do_show' => 'showentries'))); 3165 } 3166 } 3167 3168 function feedback_init_feedback_session() { 3169 //initialize the feedback-Session - not nice at all!! 3170 global $SESSION; 3171 if (!empty($SESSION)) { 3172 if (!isset($SESSION->feedback) OR !is_object($SESSION->feedback)) { 3173 $SESSION->feedback = new stdClass(); 3174 } 3175 } 3176 } 3177 3178 /** 3179 * Return a list of page types 3180 * @param string $pagetype current page type 3181 * @param stdClass $parentcontext Block's parent context 3182 * @param stdClass $currentcontext Current context of block 3183 */ 3184 function feedback_page_type_list($pagetype, $parentcontext, $currentcontext) { 3185 $module_pagetype = array('mod-feedback-*'=>get_string('page-mod-feedback-x', 'feedback')); 3186 return $module_pagetype; 3187 } 3188 3189 /** 3190 * Move save the items of the given $feedback in the order of $itemlist. 3191 * @param string $itemlist a comma separated list with item ids 3192 * @param stdClass $feedback 3193 * @return bool true if success 3194 */ 3195 function feedback_ajax_saveitemorder($itemlist, $feedback) { 3196 global $DB; 3197 3198 $result = true; 3199 $position = 0; 3200 foreach ($itemlist as $itemid) { 3201 $position++; 3202 $result = $result && $DB->set_field('feedback_item', 3203 'position', 3204 $position, 3205 array('id'=>$itemid, 'feedback'=>$feedback->id)); 3206 } 3207 return $result; 3208 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:29:05 2014 | Cross-referenced by PHPXref 0.7.1 |