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