MDL-14522 - new capability "receivemail" for better control who gets the email after
[moodle.git] / mod / feedback / lib.php
1 <?php // $Id$
2 /**
3 * includes the main-part of feedback-functions
4 *
5 * @version $Id$
6 * @author Andreas Grabs
7 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
8 * @package feedback
9 */
11 /// Library of functions and constants for module feedback
13 define('FEEDBACK_INCLUDE_TEST', 1);
14 define('FEEDBACK_ANONYMOUS_YES', 1);
15 define('FEEDBACK_ANONYMOUS_NO', 2);
16 define('FEEDBACK_MIN_ANONYMOUS_COUNT_IN_GROUP', 2);
17 define('FEEDBACK_DECIMAL', '.');
18 define('FEEDBACK_THOUSAND', ',');
19 define('FEEDBACK_RESETFORM_RESET', 'feedback_reset_data_');
20 define('FEEDBACK_RESETFORM_DROP', 'feedback_drop_feedback_');
21 define('FEEDBACK_MAX_PIX_LENGTH', '400'); //max. Breite des grafischen Balkens in der Auswertung
23 $feedback_names = feedback_load_feedback_items('mod/feedback/item');
25 /**
26 * this will create a new instance and return the id number 
27 * of the new instance.
28 * @param object $feedback the object given by mod_feedback_mod_form
29 * @return int
30 */
31 function feedback_add_instance($feedback) {
33     $feedback->timemodified = time();
34     $feedback->id = '';
36     //check if openenable and/or closeenable is set and set correctly to save in db
37     if(empty($feedback->openenable)) {
38         $feedback->timeopen = 0;
39     }
40     if(empty($feedback->closeenable)) {
41         $feedback->timeclose = 0;
42     }
43     if(empty($feedback->site_after_submit)) {
44         $feedback->site_after_submit = '';
45     }
47     //saving the feedback in db
48     if(!$feedbackid = insert_record("feedback", $feedback)) {
49         return false;
50     }
51     
52     feedback_set_events($feedback);
53     
54     return $feedbackid;
55 }
57 /**
58 * this will update a given instance
59 * @param object $feedback the object given by mod_feedback_mod_form
60 * @return boolean
61 */
62 function feedback_update_instance($feedback) {
64     $feedback->timemodified = time();
65     $feedback->id = $feedback->instance;
67     //check if openenable and/or closeenable is set and set correctly to save in db
68     if(empty($feedback->openenable)) {
69         $feedback->timeopen = 0;
70     }
71     if(empty($feedback->closeenable)) {
72         $feedback->timeclose = 0;
73     }
74     if(empty($feedback->site_after_submit)) {
75         $feedback->site_after_submit = '';
76     }
78     //save the feedback into the db
79     if(!update_record("feedback", $feedback)) {
80         return false;
81     }
83     //create or update the new events
84     feedback_set_events($feedback);
85      
86     return true;
87 }
89 /**
90 * this will delete a given instance.
91 * all referenced data also will be deleted
92 * @param int $id the instanceid of feedback
93 * @return boolean
94 */
95 function feedback_delete_instance($id) {
96     //get all referenced items
97     $feedbackitems = get_records('feedback_item', 'feedback', $id);
98     
99     //deleting all referenced items and values
100     if (is_array($feedbackitems)){
101         foreach($feedbackitems as $feedbackitem){
102             @delete_records("feedback_value", "item", $feedbackitem->id);
103             @delete_records("feedback_valuetmp", "item", $feedbackitem->id);
104         }
105         @delete_records("feedback_item", "feedback", $id);
106     }
107     
108     //deleting the referenced tracking data
109     @delete_records('feedback_tracking', 'feedback', $id);
110     
111     //deleting the completeds
112     @delete_records("feedback_completed", "feedback", $id);
113     
114     //deleting the unfinished completeds
115     @delete_records("feedback_completedtmp", "feedback", $id);
116     
117     //deleting old events
118     @delete_records('event', 'modulename', 'feedback', 'instance', $id);
119     return @delete_records("feedback", "id", $id);
122 /**
123 * this is called after deleting all instances if the course will be deleted.
124 * only templates have to be deleted
125 * @param object $course
126 * @return boolean
127 */
128 function feedback_delete_course($course) {
129     //delete all templates of given course
130     return delete_records('feedback_template', 'course', $course->id);
133 /**
134 * Return a small object with summary information about what a 
135 * user has done with a given particular instance of this module
136 * Used for user activity reports.
137 * $return->time = the time they did it
138 * $return->info = a short text description
139 * @param object $course
140 * @param object $user
141 * @param object $mod
142 * @param object $feedback
143 * @return object
144 */
145 function feedback_user_outline($course, $user, $mod, $feedback) {
147     return $return;
150 /**
151 * Print a detailed representation of what a  user has done with
152 * a given particular instance of this module, for user activity reports.
153 * @param object $course
154 * @param object $user
155 * @param object $mod
156 * @param object $feedback
157 * @return object
158 */
159 function feedback_user_complete($course, $user, $mod, $feedback) {
161     return true;
165 function feedback_cron () {
166     return true;
169 function feedback_grades($feedbackid) {
171     return NULL;
174 function feedback_get_participants($feedbackid) {
176     return false;
179 function feedback_scale_used ($feedbackid,$scaleid) {
180     $return = false;
182     return $return;
185 /** 
186  * This function is used by the remove_course_userdata function in moodlelib.
187  * If this function exists, remove_course_userdata will execute it.
188  * This function will remove all completeds from the specified feedback.
189  * @param object $data
190  * @param boolean $showfeedback
191  * @return void
192  */
193 function feedback_delete_userdata($data, $showfeedback=true) {
194     global $CFG;
195     
196     $resetfeedbacks = array();
197     $dropfeedbacks = array();
198     
199     //get the relevant entries from $data
200     foreach($data as $key => $value) {
201         switch(true) {
202             case substr($key, 0, strlen(FEEDBACK_RESETFORM_RESET)) == FEEDBACK_RESETFORM_RESET:
203                 if($value == 1) {
204                     $templist = explode('_', $key);
205                     if(isset($templist[3]))$resetfeedbacks[] = intval($templist[3]);
206                 }
207             break;
208             case substr($key, 0, strlen(FEEDBACK_RESETFORM_DROP)) == FEEDBACK_RESETFORM_DROP:
209                 if($value == 1) {
210                     $templist = explode('_', $key);
211                     if(isset($templist[3]))$dropfeedbacks[] = intval($templist[3]);
212                 }
213             break;
214         }
215     }
216     
217     //reset the selected feedbacks
218     foreach($resetfeedbacks as $id) {
219         feedback_delete_all_completeds($id);
220     }
221     
222     //drop the selected feedbacks
223     foreach($dropfeedbacks as $id) {
224         $cm = get_coursemodule_from_instance('feedback', $id);
225         feedback_delete_instance($id);
226         feedback_delete_course_module($cm->id);
227     }
230 /** 
231  * Called by course/reset.php and shows the formdata by coursereset.
232  * it prints checkboxes for each feedback available at the given course
233  * there are two checkboxes: 1) delete userdata and keep the feedback 2) delete userdata and drop the feedback
234  * @param object $course
235  * @return void
236  */
237 function feedback_reset_course_form($course) {
238     echo get_string('resetting_feedbacks', 'feedback'); echo ':<br />';
239     if(!$feedbacks = get_records('feedback', 'course', $course->id, 'name'))return;
240     
241     foreach($feedbacks as $feedback) {
242         echo '<p>';
243         echo get_string('name','feedback').': '.$feedback->name.'<br />';
244         print_checkbox(FEEDBACK_RESETFORM_RESET.$feedback->id, 1, true, get_string('resetting_data','feedback'), '', '');  echo '<br />';
245         print_checkbox(FEEDBACK_RESETFORM_DROP.$feedback->id, 1, false, get_string('drop_feedback','feedback'), '', '');
246         echo '</p>';
247     }
250 /** 
251  *  This creates new events given as timeopen and closeopen by $feedback.
252  *  @param object $feedback
253  *  @return void
254  */
255 function feedback_set_events($feedback) {
256     // adding the feedback to the eventtable (I have seen this at quiz-module)
257     delete_records('event', 'modulename', 'feedback', 'instance', $feedback->id);
259     // the open-event
260     if($feedback->timeopen > 0) {
261         $event = NULL;
262         $event->name          = get_string('start', 'feedback').' '.$feedback->name;
263         $event->description = $feedback->summary;
264         $event->courseid     = $feedback->course;
265         $event->groupid      = 0;
266         $event->userid        = 0;
267         $event->modulename  = 'feedback';
268         $event->instance     = $feedbackid;
269         $event->eventtype    = 'open';
270         $event->timestart    = $feedback->timeopen;
271         $event->visible      = instance_is_visible('feedback', $feedback);
272         if($feedback->timeclose > 0) {
273             $event->timeduration = ($feedback->timeclose - $feedback->timeopen);
274         } else {
275             $event->timeduration = 0;
276         }
277     
278         add_event($event);
279     }
281     // the close-event
282     if($feedback->timeclose > 0) {
283         $event = NULL;
284         $event->name          = get_string('stop', 'feedback').' '.$feedback->name;
285         $event->description = $feedback->summary;
286         $event->courseid     = $feedback->course;
287         $event->groupid      = 0;
288         $event->userid        = 0;
289         $event->modulename  = 'feedback';
290         $event->instance     = $feedbackid;
291         $event->eventtype    = 'close';
292         $event->timestart    = $feedback->timeclose;
293         $event->visible      = instance_is_visible('feedback', $feedback);
294         $event->timeduration = 0;
296         add_event($event);
297     }
300 /** 
301  *  this function is called by {@link feedback_delete_userdata()}
302  *  it drops the feedback-instance from the course_module table
303  *  @param int $id the id from the coursemodule
304  *  @return boolean
305  */
306 function feedback_delete_course_module($id) {
307     if (!$cm = get_record('course_modules', 'id', $id)) {
308         return true;
309     }
310     return delete_records('course_modules', 'id', $cm->id);
315 ////////////////////////////////////////////////
316 //functions to handle capabilities
317 ////////////////////////////////////////////////
319 /** 
320  *  returns the context-id related to the given coursemodule-id
321  *  @param int $cmid the coursemodule-id
322  *  @return object $context
323  */
324 function feedback_get_context($cmid) {
325     static $context;
326     
327     if(isset($context)) return $context;
328     
329     if (!$context = get_context_instance(CONTEXT_MODULE, $cmid)) {
330             print_error('badcontext');
331     }
332     return $context;
335 /** 
336  *  get the capabilities for the feedback
337  *  @param int $cmid
338  *  @return object the available capabilities from current user
339  */
340 function feedback_load_capabilities($cmid) {
341     static $cb;
342     
343     if(isset($cb)) return $cb;
344     
345     $context = feedback_get_context($cmid);
346     
347     $cb = new object;
348     $cb->view = has_capability('mod/feedback:view', $context, NULL, false);
349     $cb->complete = has_capability('mod/feedback:complete', $context, NULL, false);
350     $cb->deletesubmissions = has_capability('mod/feedback:deletesubmissions', $context, NULL, false);
351     $cb->mapcourse = has_capability('mod/feedback:mapcourse', $context, NULL, false);
352     $cb->edititems = has_capability('mod/feedback:edititems', $context, NULL, false);
353     $cb->viewreports = has_capability('mod/feedback:viewreports', $context, NULL, false);
354     $cb->receivemail = has_capability('mod/feedback:receivemail', $context, NULL, false);
355     $cb->createprivatetemplate = has_capability('mod/feedback:createprivatetemplate', $context, NULL, false);
356     $cb->createpublictemplate = has_capability('mod/feedback:createpublictemplate', $context, NULL, false);
357     $cb->deletetemplate = has_capability('mod/feedback:deletetemplate', $context, NULL, false);
358     
359     $cb->siteadmin = has_capability('moodle/site:doanything', $context);
360     
361     $cb->viewhiddenactivities = has_capability('moodle/course:viewhiddenactivities', $context, NULL, false);
362     
363     return $cb;
367 /** 
368  *  get the capabilities for the course.
369  *  this is used by feedback/index.php
370  *  @param int $courseid
371  *  @return object the available capabilities from current user
372  */
373 function feedback_load_course_capabilities($courseid) {
374     static $ccb;
375     
376     if(isset($ccb)) return $ccb;
377     
378     $context = get_context_instance(CONTEXT_COURSE, $courseid);
379     
380     $ccb = new object;
381     $ccb->view = has_capability('mod/feedback:view', $context, NULL, false);
382     $ccb->complete = has_capability('mod/feedback:complete', $context, NULL, false);
383     $ccb->deletesubmissions = has_capability('mod/feedback:deletesubmissions', $context, NULL, false);
384     $ccb->mapcourse = has_capability('mod/feedback:mapcourse', $context, NULL, false);
385     $ccb->edititems = has_capability('mod/feedback:edititems', $context, NULL, false);
386     $ccb->viewreports = has_capability('mod/feedback:viewreports', $context, NULL, false);
387     $ccb->receivemail = has_capability('mod/feedback:receivemail', $context, NULL, false);
388     $ccb->createprivatetemplate = has_capability('mod/feedback:createprivatetemplate', $context, NULL, false);
389     $ccb->createpublictemplate = has_capability('mod/feedback:createpublictemplate', $context, NULL, false);
390     $ccb->deletetemplate = has_capability('mod/feedback:deletetemplate', $context, NULL, false);
391     
392     $ccb->siteadmin = has_capability('moodle/site:doanything', $context);
393     
394     $ccb->viewhiddenactivities = has_capability('moodle/course:viewhiddenactivities', $context, NULL, false);
395     
396     return $ccb;
400 /** 
401  *  returns true if the current role is faked by switching role feature
402  *  @return boolean
403  */
404 function feedback_check_is_switchrole(){
405     global $USER;
406     if(isset($USER->switchrole) AND is_array($USER->switchrole) AND count($USER->switchrole) > 0) {
407         return true;
408     }
409     return false;
412 /** 
413  *  get users which have the complete-capability
414  *  @param int $cmid
415  *  @param mixed $groups single groupid or array of groupids - group(s) user is in
416  *  @return object the userrecords
417  */
418 function feedback_get_complete_users($cmid, $groups = false) {
420     if (!$context = get_context_instance(CONTEXT_MODULE, $cmid)) {
421             print_error('badcontext');
422     }
423     
424     //description of the call below: get_users_by_capability($context, $capability, $fields='', $sort='', $limitfrom='', $limitnum='', $groups='', $exceptions='', $doanything=true)
425     return get_users_by_capability($context, 'mod/feedback:complete', '', 'lastname', '', '', $groups, '', false);
428 /** 
429  *  get users which have the viewreports-capability
430  *  @param int $cmid
431  *  @param mixed $groups single groupid or array of groupids - group(s) user is in
432  *  @return object the userrecords
433  */
434 function feedback_get_viewreports_users($cmid, $groups = false) {
436     if (!$context = get_context_instance(CONTEXT_MODULE, $cmid)) {
437             print_error('badcontext');
438     }
439     
440     //description of the call below: get_users_by_capability($context, $capability, $fields='', $sort='', $limitfrom='', $limitnum='', $groups='', $exceptions='', $doanything=true)
441     return get_users_by_capability($context, 'mod/feedback:viewreports', '', 'lastname', '', '', $groups, '', false);
444 /** 
445  *  get users which have the receivemail-capability
446  *  @param int $cmid
447  *  @param mixed $groups single groupid or array of groupids - group(s) user is in
448  *  @return object the userrecords
449  */
450 function feedback_get_receivemail_users($cmid, $groups = false) {
452     if (!$context = get_context_instance(CONTEXT_MODULE, $cmid)) {
453             print_error('badcontext');
454     }
455     
456     //description of the call below: get_users_by_capability($context, $capability, $fields='', $sort='', $limitfrom='', $limitnum='', $groups='', $exceptions='', $doanything=true)
457     return get_users_by_capability($context, 'mod/feedback:receivemail', '', 'lastname', '', '', $groups, '', false);
460 ////////////////////////////////////////////////
461 //functions to handle the templates
462 ////////////////////////////////////////////////
463 ////////////////////////////////////////////////
465 /** 
466  *  creates a new template-record.
467  *  @param int $courseid
468  *  @param string $name the name of template shown in the templatelist
469  *  @param int $ispublic 0:privat 1:public
470  *  @return int the new templateid
471  */
472 function feedback_create_template($courseid, $name, $ispublic = 0) {
473     $templ->id = '';
474     $templ->course = $courseid;
475     
476     $templ->name = addslashes($name);
477     
478     $templ->ispublic = $ispublic;
479     return insert_record('feedback_template', $templ);
482 /** 
483  *  creates new template items.
484  *  all items will be copied and the attribute feedback will be set to 0
485  *  and the attribute template will be set to the new templateid
486  *  @param object $feedback
487  *  @param string $name the name of template shown in the templatelist
488  *  @param int $ispublic 0:privat 1:public
489  *  @return boolean
490  */
491 function feedback_save_as_template($feedback, $name, $ispublic = 0) {
492     $feedbackitems = get_records('feedback_item', 'feedback', $feedback->id);
493     if(!is_array($feedbackitems)){
494         return false;
495     }
496     
497     if(!$newtempl = feedback_create_template($feedback->course, $name, $ispublic)) {
498         return false;
499     }
500     //create items of this new template
501     foreach($feedbackitems as $item) {
502         $item->id = '';
503         $item->feedback = 0;
504         $item->template = $newtempl;
505         $item->name = addslashes($item->name);
506         $item->presentation = addslashes($item->presentation);
507         insert_record('feedback_item', $item);
508     }
509     return true;
512 /** 
513  *  deletes all feedback_items related to the given template id
514  *  @param int $id the templateid
515  *  @return void
516  */
517 function feedback_delete_template($id) {
518     @delete_records("feedback_item", "template", $id);
519     @delete_records("feedback_template", "id", $id);
522 /** 
523  *  creates new feedback_item-records from template.
524  *  if $deleteold is set true so the existing items of the given feedback will be deleted
525  *  if $deleteold is set false so the new items will be appanded to the old items
526  *  @param object $feedback
527  *  @param int $templateid
528  *  @param boolean $deleteold
529  */
530 function feedback_items_from_template($feedback, $templateid, $deleteold = false) {
531     //get all templateitems
532     if(!$templitems = get_records('feedback_item', 'template', $templateid)) {
533         return false;
534     }
535     
536     //if deleteold then delete all old items before
537     //get all items
538     if($deleteold) {
539         if($feedbackitems = get_records('feedback_item', 'feedback', $feedback->id)){
540             //delete all items of this feedback
541             foreach($feedbackitems as $item) {
542                 feedback_delete_item($item->id, false);
543             }
544             //delete tracking-data
545             @delete_records('feedback_tracking', 'feedback', $feedback->id);
546             @delete_records('feedback_completed', 'feedback', $feedback->id);
547             @delete_records('feedback_completedtmp', 'feedback', $feedback->id);
548             $positionoffset = 0;
549         }
550     }else {
551         //if the old items are kept the new items will be appended
552         //therefor the new position has an offset
553         $positionoffset = count_records('feedback_item', 'feedback', $feedback->id);
554     }
555     
556     foreach($templitems as $newitem) {
557         $newitem->id = '';
558         $newitem->feedback = $feedback->id;
559         $newitem->template = 0;
560         $newitem->name = addslashes($newitem->name);
561         $newitem->presentation = addslashes($newitem->presentation);
562         $newitem->position = $newitem->position + $positionoffset;
563         insert_record('feedback_item', $newitem);
564     }
567 /** 
568  *  get the list of available templates.
569  *  if the $onlyown param is set true so only templates from own course will be served
570  *  this is important for droping templates
571  *  @param object $course
572  *  @param boolean $onlyown
573  *  @return array the template recordsets
574  */
575 function feedback_get_template_list($course, $onlyown = false) {
576     if($onlyown) {
577         $templates = get_records('feedback_template', 'course', $course->id);
578     } else {
579         $templates = get_records_select('feedback_template', 'course = ' . $course->id . ' OR ispublic = 1');
580     }
581     return $templates;
584 ////////////////////////////////////////////////
585 //Handling der Items
586 ////////////////////////////////////////////////
587 ////////////////////////////////////////////////
589 /** 
590  *  load the available item plugins from given subdirectory of $CFG->dirroot
591  *  the default is "mod/feedback/item"
592  *  @param string $dir the subdir
593  *  @return array pluginnames as string
594  */
595 function feedback_load_feedback_items($dir = 'mod/feedback/item') {
596     global $CFG;
597     $names =get_list_of_plugins($dir);
598     $ret_names = array();
600     foreach($names as $name) {
601         require_once($CFG->dirroot.'/'.$dir.'/'.$name.'/lib.php');
602         if(class_exists('feedback_item_'.$name)) {
603           $ret_names[] = $name;
604         }
605     }
606     return $ret_names;
609 /** 
610  *  load the available item plugins to use as dropdown-options
611  *  @return array pluginnames as string
612  */
613 function feedback_load_feedback_items_options() {
614     global $CFG;
615     
616     $feedback_options = array("pagebreak" => get_string('add_pagebreak', 'feedback'));
617     
618     if (!$feedback_names = feedback_load_feedback_items('mod/feedback/item')) {
619         return array();
620     }
621     
622     foreach($feedback_names as $fn) {
623         $feedback_options[$fn] = get_string($fn,'feedback');
624     }
625     asort($feedback_options);
626     $feedback_options = array_merge( array(' ' => get_string('select')), $feedback_options );    
627     return $feedback_options;
630 /** 
631  *  creates a new item-record
632  *  @param object $data the data from edit_item_form
633  *  @return int the new itemid
634  */
635 function feedback_create_item($data) {
636     $item = new object;
637     $item->id = '';
638     $item->feedback = intval($data->feedbackid);
640     $item->template=0;
641     if (isset($data->templateid)) {
642                 $item->template = intval($data->templateid);
643     }    
645     $itemname = trim($data->itemname);
646     $item->name = addslashes($itemname ? $data->itemname : get_string('no_itemname', 'feedback'));
647     
648     //get the used class from item-typ
649     $itemclass = 'feedback_item_'.$data->typ;
650     //get the instance of the item class
651     $itemobj = new $itemclass();
652     $item->presentation = addslashes($itemobj->get_presentation($data));
653     
654     $item->hasvalue = $itemobj->get_hasvalue();
655     
656     $item->typ = $data->typ;
657     $item->position = $data->position;
659     $item->required=0;
660     if (isset($data->required)) {
661                 $item->required=$data->required;
662     }    
664     return insert_record('feedback_item', $item);
667 /** 
668  *  save the changes of a given item.
669  *  @param object $item
670  *  @param object $data the data from edit_item_form
671  *  @return boolean
672  */
673 function feedback_update_item($item, $data = null){
674     if($data != null){
675         $itemname = trim($data->itemname);
676         $item->name = addslashes($itemname ? $data->itemname : get_string('no_itemname', 'feedback'));
677     
678         //get the used class from item-typ
679         $itemclass = 'feedback_item_'.$data->typ;
680         //get the instance of the item class
681         $itemobj = new $itemclass();
682         $item->presentation = addslashes($itemobj->get_presentation($data));
684         $item->required=0;
685         if (isset($data->required)) {
686                 $item->required=$data->required;
687         } 
688     }else {
689         $item->name = addslashes($item->name);
690         $item->presentation = addslashes($item->presentation);
691     }
693     return update_record("feedback_item", $item);
696 /** 
697  *  deletes a item and also deletes all related values
698  *  @param int $itemid
699  *  @param boolean $renumber should the kept items renumbered Yes/No
700  *  @return void
701  */
702 function feedback_delete_item($itemid, $renumber = true){
703     $item = get_record('feedback_item', 'id', $itemid);
704     @delete_records("feedback_value", "item", $itemid);
705     @delete_records("feedback_valuetmp", "item", $itemid);
706     delete_records("feedback_item", "id", $itemid);
707     if($renumber) {
708         feedback_renumber_items($item->feedback);
709     }
712 /** 
713  *  deletes all items of the given feedbackid
714  *  @param int $feedbackid
715  *  @return void
716  */
717 function feedback_delete_all_items($feedbackid){
718     if(!$items = get_records('feedback_item', 'feedback', $feedbackid)) {
719         return;
720     }
721     foreach($items as $item) {
722         feedback_delete_item($item->id, false);
723     }
724     @delete_records('feedback_completedtmp', 'feedback', $feedbackid);
725     @delete_records('feedback_completed', 'feedback', $feedbackid);
728 /** 
729  *  this function toggled the item-attribute required (yes/no)
730  *  @param object $item
731  *  @return boolean
732  */
733 function feedback_switch_item_required($item) {
734     if($item->required == 1) {
735         $item->required = 0;
736     } else {
737         $item->required = 1;
738     }
739     $item->name = addslashes($item->name);
740     $item->presentation = addslashes($item->presentation);
741     return update_record('feedback_item', $item);
744 /** 
745  *  renumbers all items of the given feedbackid
746  *  @param int $feedbackid
747  *  @return void
748  */
749 function feedback_renumber_items($feedbackid){
750     $items = get_records('feedback_item', 'feedback', $feedbackid, 'position');
751     $pos = 1;
752     if($items) {
753         foreach($items as $item){
754             $item->position = $pos;
755             $pos++;
756             feedback_update_item($item);
757         }
758     }
761 /** 
762  *  this decreases the position of the given item
763  *  @param object $item
764  *  @return void
765  */
766 function feedback_moveup_item($item){
767     if($item->position == 1) return;
768     $item_before = get_record_select('feedback_item', 'feedback = '.$item->feedback.' AND position = '.$item->position . ' - 1');
769     $item_before->position = $item->position;
770     $item->position--;
771     feedback_update_item($item_before);
772     feedback_update_item($item);
775 /** 
776  *  this increased the position of the given item
777  *  @param object $item
778  *  @return void
779  */
780 function feedback_movedown_item($item){
781     if(!$item_after = get_record_select('feedback_item', 'feedback = '.$item->feedback.' AND position = '.$item->position . ' + 1'))
782     {
783         return;
784     }
785     
786     $item_after->position = $item->position;
787     $item->position++;
788     feedback_update_item($item_after);
789     feedback_update_item($item);
792 /** 
793  *  here the position of the given item will be set to the value in $pos
794  *  @param object $moveitem
795  *  @param int $pos
796  *  @return boolean
797  */
798 function feedback_move_item($moveitem, $pos){
799     if($moveitem->position == $pos) return true;
800     if(!$allitems = get_records('feedback_item', 'feedback', $moveitem->feedback, 'position')){
801         return false;
802     }
803     if(is_array($allitems)) {
804         $index = 1;
805         foreach($allitems as $item) {
806             if($item->id == $moveitem->id) continue; //the moving item is handled special
807             
808             if($index == $pos) {
809                 $moveitem->position = $index;
810                 feedback_update_item($moveitem);
811                 $index++;
812             }
813             $item->position = $index;
814             feedback_update_item($item);
815             $index++;
816         }
817         if($pos >= count($allitems)) {
818             $moveitem->position = $index;
819             feedback_update_item($moveitem);
820         }
821         return true;
822     }
823     return false;
826 /** 
827  *  prints the given item.
828  *  if $readonly is set true so the ouput only is for showing responses and not for editing or completing.
829  *  each item-class has an own print_item function implemented.
830  *  @param object $item the item what we want to print out
831  *  @param mixed $value the value if $readonly is set true and we showing responses
832  *  @param boolean $readonly
833  *  @param boolean $edit should the item print out for completing or for editing?
834  *  @param boolean $highlightrequire if this set true and the value are false on completing so the item will be highlighted
835  *  @return void
836  */
837 function feedback_print_item($item, $value = false, $readonly = false, $edit = false, $highlightrequire = false){
838     if($item->typ == 'pagebreak') return;
839     if($readonly)$ro = 'readonly="readonly" disabled="disabled"';
840         
841     //get the class of the given item-typ
842     $itemclass = 'feedback_item_'.$item->typ;
843     //get the instance of the item-class
844     $itemobj = new $itemclass();
845     $itemobj->print_item($item, $value, $readonly, $edit, $highlightrequire);
848 /** 
849  *  if the user completes a feedback and there is a pagebreak so the values are saved temporary.
850  *  the values are saved permanently not until the user click on save button
851  *  @param object $feedbackcompleted
852  *  @return object temporary saved completed-record
853  */
854 function feedback_set_tmp_values($feedbackcompleted){
855     //first we create a completedtmp
856     $tmpcpl = new object();
857     foreach($feedbackcompleted as $key => $value) {
858         $tmpcpl->{$key} = $value;
859     }
860     // $tmpcpl = $feedbackcompleted;
861     $tmpcpl->id = '';
862     $tmpcpl->timemodified = time();
863     if(!$tmpcpl->id = insert_record('feedback_completedtmp', $tmpcpl)) {
864         error('failed create completedtmp');
865     }
866     //get all values of original-completed
867     if(!$values = get_records('feedback_value', 'completed', $feedbackcompleted->id)) {
868         return;
869     }
870     foreach($values as $value) {
871         $value->id = '';
872         $value->completed = $tmpcpl->id;
873         $value->value = addslashes($value->value);
874         insert_record('feedback_valuetmp', $value);
875     }
876     return $tmpcpl;
879 /** 
880  *  this saves the temporary saved values permanently
881  *  @param object $feedbackcompletedtmp the temporary completed
882  *  @param object $feedbackcompleted the target completed
883  *  @param int $userid
884  *  @return int the id of the completed
885  */
886 function feedback_save_tmp_values($feedbackcompletedtmp, $feedbackcompleted, $userid) {
887     $tmpcplid = $feedbackcompletedtmp->id;
888     if(!$feedbackcompleted) {
890         //first we create a completedtmp
891         $newcpl = new object();
892         foreach($feedbackcompletedtmp as $key => $value) {
893             $newcpl->{$key} = $value;
894         }
896         $newcpl->id = '';
897         $newcpl->userid = $userid;
898         $newcpl->timemodified = time();
899         if(!$newcpl->id = insert_record('feedback_completed', $newcpl)) {
900             error('failed create completed');
901         }
902         //get all values of tmp-completed
903         if(!$values = get_records('feedback_valuetmp', 'completed', $feedbackcompletedtmp->id)) {
904             return false;
905         }
907         foreach($values as $value) {
908             $value->id = '';
909             $value->completed = $newcpl->id;
910             insert_record('feedback_value', $value);
911         }
912         //drop all the tmpvalues
913         delete_records('feedback_valuetmp', 'completed', $tmpcplid);
914         delete_records('feedback_completedtmp', 'id', $tmpcplid);
915         return $newcpl->id;
916     }else {
917         //first drop all existing values
918         delete_records('feedback_value', 'completed', $feedbackcompleted->id);
919         //update the current completed
920         $feedbackcompleted->timemodified = time();
921         update_record('feedback_completed', $feedbackcompleted);
922         //save all the new values from feedback_valuetmp
923         //get all values of tmp-completed
924         if(!$values = get_records('feedback_valuetmp', 'completed', $feedbackcompletedtmp->id)) {
925             return false;
926         }
927         foreach($values as $value) {
928             $value->id = '';
929             $value->completed = $feedbackcompleted->id;
930             insert_record('feedback_value', $value);
931         }
932         //drop all the tmpvalues
933         delete_records('feedback_valuetmp', 'completed', $tmpcplid);
934         delete_records('feedback_completedtmp', 'id', $tmpcplid);
935         return $feedbackcompleted->id;
936     }
939 /** 
940  *  deletes the given temporary completed and all related temporary values
941  *  @param int $tmpcplid
942  *  @return void
943  */
944 function feedback_delete_completedtmp($tmpcplid) {
945         delete_records('feedback_valuetmp', 'completed', $tmpcplid);
946         delete_records('feedback_completedtmp', 'id', $tmpcplid);
949 ////////////////////////////////////////////////
950 ////////////////////////////////////////////////
951 ////////////////////////////////////////////////
952 //functions to handle the pagebreaks
953 ////////////////////////////////////////////////
955 /** 
956  *  this creates a pagebreak.
957  *  a pagebreak is a special kind of item
958  *  @param int $feedbackid
959  *  @return mixed false if there already is a pagebreak on last position or the id of the pagebreak-item
960  */
961 function feedback_create_pagebreak($feedbackid) {
962     //check if there already is a pagebreak on the last position
963     $lastposition = count_records('feedback_item', 'feedback', $feedbackid);
964     if($lastposition == feedback_get_last_break_position($feedbackid)) {
965         return false;
966     }
967     
968     $item = new object();
969     $item->id = '';
970     $item->feedback = $feedbackid;
972     $item->template=0;
974     $item->name = '';
975     
976     $item->presentation = '';
977     $item->hasvalue = 0;
978     
979     $item->typ = 'pagebreak';
980     $item->position = $lastposition + 1;
982     $item->required=0;
984     return insert_record('feedback_item', $item);
987 /** 
988  *  get all positions of pagebreaks in the given feedback
989  *  @param int $feedbackid
990  *  @return array all ordered pagebreak positions
991  */
992 function feedback_get_all_break_positions($feedbackid) {
993     if(!$allbreaks = get_records_select_menu('feedback_item', "typ = 'pagebreak' AND feedback = ".$feedbackid, 'position', 'id, position')) return false;
994     return array_values($allbreaks);
997 /** 
998  *  get the position of the last pagebreak
999  *  @param int $feedbackid
1000  *  @return int the position of the last pagebreak
1001  */
1002 function feedback_get_last_break_position($feedbackid) {
1003     if(!$allbreaks = feedback_get_all_break_positions($feedbackid)) return false;
1004     return $allbreaks[count($allbreaks) - 1];
1007 /** 
1008  *  this returns the position where the user can continue the completing.
1009  *  @param int $feedbackid
1010  *  @param int $courseid
1011  *  @param string $guestid this id will be saved temporary and is unique
1012  *  @return int the position to continue
1013  */
1014 function feedback_get_page_to_continue($feedbackid, $courseid = false, $guestid) {
1015     global $CFG, $USER;
1016     
1017     //is there any break?
1018     
1019     if(!$allbreaks = feedback_get_all_break_positions($feedbackid)) return false;
1020     
1021     if($courseid) {
1022         $courseselect = "fv.course_id = ".$courseid;
1023     }else {
1024         $courseselect = "1";
1025     }
1026     
1027     if($guestid) {
1028         $userselect = "AND fc.guestid = '".$guestid."'";
1029         $usergroup = "GROUP BY fc.guestid";
1030     }else {
1031         $userselect = "AND fc.userid = ".$USER->id;
1032         $usergroup = "GROUP BY fc.userid";
1033     }
1034     
1035     
1036     $sql =  "SELECT MAX(fi.position)
1037                 FROM ".$CFG->prefix."feedback_completedtmp AS fc, ".$CFG->prefix."feedback_valuetmp AS fv, ".$CFG->prefix."feedback_item AS fi
1038                 WHERE fc.id = fv.completed
1039                     ".$userselect."
1040                     AND fc.feedback = ".$feedbackid."
1041                     AND ".$courseselect."
1042                     AND fi.id = fv.item
1043                 ".$usergroup;
1044     
1045     $lastpos = get_field_sql($sql);
1047     //the index of found pagebreak is the searched pagenumber
1048     foreach($allbreaks as $pagenr => $br) {
1049         if($lastpos < $br) return $pagenr;
1050     }
1051     return count($allbreaks);
1054 ////////////////////////////////////////////////
1055 ////////////////////////////////////////////////
1056 ////////////////////////////////////////////////
1057 //functions to handle the values
1058 ////////////////////////////////////////////////
1060 /** 
1061  *  this saves the values of an completed.
1062  *  if the param $tmp is set true so the values are saved temporary in table feedback_valuetmp
1063  *  if there is already a completed and the userid is set so the values are updated
1064  *  on all other things new value records will be created
1065  *  @param object $data the data from complete form
1066  *  @param int $userid
1067  *  @param boolean $tmp
1068  *  @return mixed false on error or the completeid
1069  */
1070 function feedback_save_values($data, $usrid, $tmp = false) {
1071     $tmpstr = $tmp ? 'tmp' : '';
1072          $time = time(); //arb
1073          $timemodified = mktime(0, 0, 0, date('m', $time),date('d', $time),date('Y', $time)); //arb
1074 //         $timemodified = time();              
1075     if($usrid == 0) {
1076         return feedback_create_values($data, $usrid, $timemodified, $tmp);
1077     }
1078     if(!$data['completedid'] or !$completed = get_record('feedback_completed'.$tmpstr, 'id', $data['completedid'])){
1079         return feedback_create_values($data, $usrid, $timemodified, $tmp);
1080     }else{
1081         $completed->timemodified = $timemodified;
1082         return feedback_update_values($data, $completed, $tmp);
1083     }
1086 /** 
1087  *  this saves the values from anonymous user such as guest on the main-site
1088  *  @param object $data the data form complete_guest form
1089  *  @param string $guestid the unique guestidentifier
1090  *  @return mixed false on error or the completeid
1091  */
1092 function feedback_save_guest_values($data, $guestid) {
1093     $timemodified = time();
1094     if(!$completed = get_record('feedback_completedtmp', 'id', $data['completedid'])){
1095         return feedback_create_values($data, 0, $timemodified, true, $guestid);
1096     }else {
1097         $completed->timemodified = $timemodified;
1098         return feedback_update_values($data, $completed, true);
1099     }
1102 /** 
1103  *  get the value from the given item related to the given completed.
1104  *  the value can come as temporary or as permanently value. the deciding is done by $tmp
1105  *  @param int $completeid
1106  *  @param int $itemid
1107  *  @param boolean $tmp
1108  *  @return mixed the value, the type depends on plugin-definition
1109  */
1110 function feedback_get_item_value($completedid, $itemid, $tmp = false) {
1111     $tmpstr = $tmp ? 'tmp' : '';
1112     return get_field('feedback_value'.$tmpstr, 'value', 'completed', $completedid, 'item', $itemid);
1115 /** 
1116  *  this function checks the correctness of values.
1117  *  the rules for this are implemented in the class of each item.
1118  *  it can be the required attribute or the value self e.g. numeric.
1119  *  the params first/lastitem are given to determine the visible range between pagebreaks.
1120  *  @param object $data the data of complete form
1121  *  @param int $firstitem the position of firstitem for checking
1122  *  @param int $lastitem the position of lastitem for checking
1123  *  @return boolean
1124  */
1125 function feedback_check_values($data, $firstitem, $lastitem) {
1126     //get all items between the first- and lastitem
1127     $select = "feedback = ".intval($data['feedbackid'])."
1128                     AND position >= ".$firstitem."
1129                     AND position <= ".$lastitem."
1130                     AND hasvalue = 1";
1131     if(!$feedbackitems = get_records_select('feedback_item', $select)) {
1132         //if no values are given so no values can be wrong ;-)
1133         return true;
1134     }
1136     foreach($feedbackitems as $item) {
1137         //the name of the input field of the completeform is given in a special form:
1138         //<item-typ>_<item-id> eg. numeric_234
1139         //this is the key to get the value for the correct item
1140         $formvalname = $item->typ . '_' . $item->id;
1141         
1142         //check if the value is set
1143         if((!isset($data[$formvalname])) AND ($item->required == 1)) {
1144             return false;
1145         }
1146         
1147         //if there is a value so save it temporary
1148         $value = isset($data[$formvalname]) ? $data[$formvalname] : '';
1150         //get the class of the item-typ
1151         $itemclass = 'feedback_item_'.$item->typ;
1152         //get the instance of the item-class
1153         $itemobj = new $itemclass();
1154         
1155         //now we let check the value by the item-class
1156         if(!$itemobj->check_value($value, $item)) {
1157             return false;
1158         }
1159     }
1160     //if no wrong values so we can return true
1161     return true;
1164 /** 
1165  *  this function create a complete-record and the related value-records.
1166  *  depending on the $tmp (true/false) the values are saved temporary or permanently
1167  *  @param object $data the data of the complete form
1168  *  @param int $userid
1169  *  @param int $timemodified
1170  *  @param boolean $tmp
1171  *  @param string $guestid a unique identifier to save temporary data
1172  *  @return mixed false on error or the completedid
1173  */
1174 function feedback_create_values($data, $usrid, $timemodified, $tmp = false, $guestid = false){
1175     $tmpstr = $tmp ? 'tmp' : '';
1176     //first we create a new completed record
1177     $completed = null;
1178     $completed->id = '';
1179     $completed->feedback = $data['feedbackid'];
1180     $completed->userid = $usrid;
1181     $completed->guestid = $guestid;
1182     $completed->timemodified = $timemodified;
1183     $completed->anonymous_response = $data['anonymous_response'];
1184     
1185     if(!$completedid = insert_record('feedback_completed'.$tmpstr, $completed)) {
1186         return false;
1187     }
1188     
1189     $completed = null;
1190     $completed = get_record('feedback_completed'.$tmpstr, 'id', $completedid);
1192     //$data includes an associative array. the keys are in the form like abc_xxx
1193     //with explode we make an array with(abc, xxx) and (abc=typ und xxx=itemnr)
1194     $keys = array_keys($data);
1195     $errcount = 0;
1196     foreach($keys as $key){
1197         //ensure the keys are what we want
1198         if(eregi('([a-z0-9]{1,})_([0-9]{1,})',$key)){            
1199             $value = null;
1200             $itemnr = explode('_', $key);
1201             $value->id = '';
1202             $value->item = intval($itemnr[1]);
1203             $value->completed = $completed->id;
1204             $value->course_id = intval($data['courseid']);
1205             
1206             //get the class of item-typ
1207             $itemclass = 'feedback_item_'.$itemnr[0];
1208             //get the instance of item-class
1209             $itemobj = new $itemclass();
1210             //the kind of values can be absolutely different so we run create_value directly by the item-class
1211             $value->value = $itemobj->create_value($data[$key]);
1213             if(!insert_record('feedback_value'.$tmpstr, $value)) {
1214                 $errcount++;
1215             }
1216         }
1217     }
1218     
1219     //if nothing is wrong so we can return the completedid otherwise false
1220     return $errcount == 0 ? $completed->id : false;
1223 /** 
1224  *  this function updates a complete-record and the related value-records.
1225  *  depending on the $tmp (true/false) the values are saved temporary or permanently
1226  *  @param object $data the data of the complete form
1227  *  @param object $completed
1228  *  @param boolean $tmp
1229  *  @return int the completedid
1230  */
1231 function feedback_update_values($data, $completed, $tmp = false){
1232     $tmpstr = $tmp ? 'tmp' : '';
1233     
1234     update_record('feedback_completed'.$tmpstr, $completed);
1235     //get the values of this completed
1236     $values = get_records('feedback_value'.$tmpstr,'completed', $completed->id);
1237     
1238     //$data includes an associative array. the keys are in the form like abc_xxx
1239     //with explode we make an array with(abc, xxx) and (abc=typ und xxx=itemnr)
1240     $keys = array_keys($data);
1241     foreach($keys as $key){
1242         //ensure the keys are what we want
1243         if(eregi('([a-z0-9]{1,})_([0-9]{1,})',$key)){            
1244             //build the new value to update([id], item, completed, value)
1245             $itemnr = explode('_', $key);
1246             $newvalue = null;
1247             $newvalue->id = '';
1248             $newvalue->item = intval($itemnr[1]);
1249             $newvalue->completed = $completed->id;
1250             $newvalue->course_id = intval($data['courseid']);
1251             
1252             //get the class of item-typ
1253             $itemclass = 'feedback_item_'.$itemnr[0];
1254             //get the instace of the item-class
1255             $itemobj = new $itemclass();
1256             //the kind of values can be absolutely different so we run create_value directly by the item-class
1257             $newvalue->value = $itemobj->create_value($data[$key]);
1258             
1259             //check, if we have to create or update the value
1260             $exist = false;
1261             foreach($values as $value){
1262                 if($value->item == $newvalue->item){
1263                     $newvalue->id = $value->id;
1264                     $exist = true;
1265                     break;
1266                 }
1267             }
1268             if($exist){
1269                 update_record('feedback_value'.$tmpstr, $newvalue);
1270             }else {
1271                 insert_record('feedback_value'.$tmpstr, $newvalue);
1272             }
1273             
1274         }
1275     }
1277     return $completed->id;
1280 /** 
1281  *  get the values of an item depending on the given groupid.
1282  *  if the feedback is anonymous so the values are shuffled
1283  *  @param object $item
1284  *  @param int $groupid
1285  *  @param int $courseid
1286  *  @return array the value-records
1287  */
1288 function feedback_get_group_values($item, $groupid = false, $courseid = false){
1289     global $CFG;
1291     //if the groupid is given?
1292     if(intval($groupid) > 0) {
1293         $query = 'SELECT fbv .  *
1294                         FROM '.$CFG->prefix . 'feedback_value AS fbv, '.$CFG->prefix . 'feedback_completed AS fbc, '.$CFG->prefix . 'groups_members AS gm
1295                         WHERE fbv.item = '.$item->id . '
1296                              AND fbv.completed = fbc.id 
1297                              AND fbc.userid = gm.userid 
1298                              AND gm.groupid = '.$groupid . '
1299                         ORDER BY fbc.timemodified';
1300         $values = get_records_sql($query);
1301     }else {
1302         if ($courseid) {
1303              $values = get_records_select('feedback_value', "item = '$item->id' and course_id = '$courseid'");
1304         } else {
1305              $values = get_records('feedback_value', 'item', $item->id);
1306         }
1307     }    
1308     if(get_field('feedback', 'anonymous', 'id', $item->feedback) == FEEDBACK_ANONYMOUS_YES) {
1309         if(is_array($values))
1310             shuffle($values);
1311     }
1312     return $values;
1315 /** 
1316  *  check for multiple_submit = false.
1317  *  if the feedback is global so the courseid must be given
1318  *  @param int $feedbackid
1319  *  @param int $courseid
1320  *  @return boolean true if the feedback already is submitted otherwise false
1321  */
1322 function feedback_is_already_submitted($feedbackid, $courseid = false) {
1323     global $USER;
1324     
1325     $select = 'userid = '.$USER->id.' AND feedback = '.$feedbackid;
1326     if(!$trackings = get_records_select_menu('feedback_tracking', $select, '', 'id, completed')) {
1327         return false;
1328     }
1330     if($courseid) {
1331         $select = 'completed IN ('.implode(',',$trackings).') AND course_id = '.$courseid;
1332         if(!$values = get_records_select('feedback_value', $select)) {
1333             return false;
1334         }
1335     }
1337     return true;
1340 /** 
1341  *  if the completion of a feedback will be continued eg. by pagebreak or by multiple submit so the complete must be found.
1342  *  if the param $tmp is set true so all things are related to temporary completeds
1343  *  @param int $feedbackid
1344  *  @param boolean $tmp
1345  *  @param int $courseid
1346  *  @param string $guestid
1347  *  return int the id of the found completed
1348  */
1349 function feedback_get_current_completed($feedbackid, $tmp = false, $courseid = false, $guestid = false) {
1350     global $USER, $CFG;
1351     
1352     $tmpstr = $tmp ? 'tmp' : '';
1353     
1354     if(!$courseid) {
1355         if($guestid) {
1356             return get_record('feedback_completed'.$tmpstr,'feedback', $feedbackid, 'guestid', $guestid);
1357         }else {
1358             return get_record('feedback_completed'.$tmpstr,'feedback', $feedbackid, 'userid', $USER->id);
1359         }
1360     }
1361     
1362     $courseid = intval($courseid);
1363     
1364     if($guestid) {
1365         $userselect = "AND fc.guestid = '".$guestid."'";
1366     }else {
1367         $userselect = "AND fc.userid = ".$USER->id;
1368     }
1369     //if courseid is set the feedback is global. there can be more than one completed on one feedback
1370     $sql =  "SELECT fc.* FROM
1371                     ".$CFG->prefix."feedback_value".$tmpstr." AS fv, ".$CFG->prefix."feedback_completed".$tmpstr." AS fc
1372                 WHERE fv.course_id = ".$courseid."
1373                     AND fv.completed = fc.id
1374                     ".$userselect."
1375                     AND fc.feedback = ".$feedbackid;
1377     if(!$sqlresult = get_records_sql($sql)) return false;
1378     foreach($sqlresult as $r) {
1379         return get_record('feedback_completed'.$tmpstr, 'id', $r->id);
1380     }
1383 /** 
1384  *  get the completeds depending on the given groupid.
1385  *  @param object $feedback
1386  *  @param int $groupid
1387  *  @return mixed array of found completeds otherwise false
1388  */
1389 function feedback_get_completeds_group($feedback, $groupid = false) {
1390     global $CFG;
1391     if(intval($groupid) > 0){
1392         $query = 'SELECT fbc.*
1393                         FROM '.$CFG->prefix . 'feedback_completed AS fbc, '.$CFG->prefix . 'groups_members AS gm
1394                         WHERE  fbc.feedback = '.$feedback->id . '
1395                             AND gm.groupid = '.$groupid . '
1396                             AND fbc.userid = gm.userid';
1397         if($values = get_records_sql($query)) {
1398             return $values;
1399         }else {return false;}
1400     }else {
1401         if($values = get_records('feedback_completed', 'feedback', $feedback->id)){
1402             return $values;
1403         }else{return false;}
1404     }
1407 /** 
1408  *  get the count of completeds depending on the given groupid.
1409  *  @param object $feedback
1410  *  @param int $groupid
1411  *  @param int $courseid
1412  *  @return mixed count of completeds or false
1413  */
1414 function feedback_get_completeds_group_count($feedback, $groupid = false, $courseid = false) {
1415     global $CFG;
1416     if($courseid > 0 AND !$groupid <= 0) {
1417         $sql = 'SELECT id, COUNT( item ) ci
1418                     FROM  '.$CFG->prefix . 'feedback_value 
1419                     WHERE  course_id  = '.$courseid.'
1420                     GROUP  BY  item ORDER BY ci DESC';
1421         if($foundrecs = get_records_sql($sql)) {
1422             $foundrecs = array_values($foundrecs);
1423             return $foundrecs[0]->ci;
1424         }
1425         return false;
1426     }
1427     if($values = feedback_get_completeds_group($feedback, $groupid)) {
1428         return sizeof($values);
1429     }else {
1430         return false;
1431     }
1434 /* get the own groupid.
1435 @param object $course
1436 @param object $cm
1437 function feedback_get_groupid($course, $cm) {
1438     $groupmode = groupmode($course, $cm);
1439     
1440     //get groupid
1441     if($groupmode > 0 && !isadmin()) {
1442         if($mygroupid = mygroupid($course->id)) {
1443             return $mygroupid[0]; //get the first groupid
1444         }
1445     }else {
1446         return false;
1447     }
1449  */
1451 /** 
1452  *  deletes all completed-recordsets from a feedback.
1453  *  all related data such as values also will be deleted
1454  *  @param int $feedbackid
1455  *  @return void
1456  */
1457 function feedback_delete_all_completeds($feedbackid) {
1458     if(!$completeds = get_records('feedback_completed', 'feedback', $feedbackid)) return;
1459     foreach($completeds as $completed) {
1460         feedback_delete_completed($completed->id);
1461     }
1464 /** 
1465  *  deletes a completed given by completedid.
1466  *  all related data such values or tracking data also will be deleted
1467  *  @param int $completedid
1468  *  @return boolean
1469  */
1470 function feedback_delete_completed($completedid) {
1471     if(!$completed = get_record('feedback_completed', 'id', $completedid)) {
1472         return false;
1473     }
1474     //first we delete all related values
1475     @delete_records('feedback_value', 'completed', $completed->id);
1476     
1477     //now we delete all tracking data
1478     if($tracking = get_record_select('feedback_tracking', " completed = ".$completed->id." AND feedback = ".$completed->feedback." ")) {
1479         @delete_records('feedback_tracking', 'completed', $completed->id);
1480     }
1481         
1482     //last we delete the completed-record
1483     return delete_records('feedback_completed', 'id', $completed->id);
1486 ////////////////////////////////////////////////
1487 ////////////////////////////////////////////////
1488 ////////////////////////////////////////////////
1489 //functions to handle sitecourse mapping
1490 ////////////////////////////////////////////////
1492 /** 
1493  *  checks if the course and the feedback is in the table feedback_sitecourse_map.
1494  *  @param int $feedbackid
1495  *  @param int $courseid
1496  *  @return int the count of records
1497  */
1498 function feedback_is_course_in_sitecourse_map($feedbackid, $courseid) {
1499     global $CFG;
1500     return count_records('feedback_sitecourse_map', 'feedbackid', $feedbackid, 'courseid', $courseid);
1503 /** 
1504  *  checks if the feedback is in the table feedback_sitecourse_map.
1505  *  @param int $feedbackid
1506  *  @return boolean
1507  */
1508 function feedback_is_feedback_in_sitecourse_map($feedbackid) {
1509     global $CFG;
1510     return record_exists('feedback_sitecourse_map', 'feedbackid', $feedbackid);
1513 /** 
1514  *  gets the feedbacks from table feedback_sitecourse_map.
1515  *  this is used to show the global feedbacks on the feedback block
1516  *  all feedbacks with the following criteria will be selected:<br />
1517  *  1) all feedbacks which id are listed together with the courseid in sitecoursemap and<br />
1518  *  2) all feedbacks which not are listed in sitecoursemap
1519  *  @param int $courseid
1520  *  @return array the feedback-records
1521  */
1522 function feedback_get_feedbacks_from_sitecourse_map($courseid) {
1523     global $CFG;
1524     
1525     //first get all feedbacks listed in sitecourse_map with named courseid
1526     $sql = "SELECT f.id as id, cm.id as cmid, f.name as name, f.timeopen as timeopen, f.timeclose as timeclose
1527               FROM {$CFG->prefix}feedback f, {$CFG->prefix}course_modules cm, {$CFG->prefix}feedback_sitecourse_map sm, {$CFG->prefix}modules m
1528               WHERE f.id = cm.instance
1529                 AND f.course = '".SITEID."'
1530                 AND m.id = cm.module 
1531                 AND m.name = 'feedback'
1532                 AND sm.courseid = $courseid 
1533                 AND sm.feedbackid = f.id";
1534     
1535     if(!$feedbacks1 = get_records_sql($sql)) {
1536         $feedbacks1 = array();
1537     }
1538     
1539     //second get all feedbacks not listed in sitecourse_map
1540     $feedbacks2 = array();
1541     $sql = "SELECT f.id as id, cm.id as cmid, f.name as name, f.timeopen as timeopen, f.timeclose as timeclose
1542               FROM {$CFG->prefix}feedback f, {$CFG->prefix}course_modules cm, {$CFG->prefix}modules m
1543               WHERE f.id = cm.instance
1544                 AND f.course = '".SITEID."'
1545                 AND m.id = cm.module
1546                 AND m.name = 'feedback'";
1547     if(!$allfeedbacks = get_records_sql($sql)) {
1548         $allfeedbacks = array();
1549     }
1550     foreach($allfeedbacks as $a) {
1551         if(!record_exists('feedback_sitecourse_map', 'feedbackid', $a->id)) {
1552             $feedbacks2[] = $a;
1553         }
1554     }
1555     
1556     return array_merge($feedbacks1, $feedbacks2);
1557     
1560 /** 
1561  *  gets the courses from table feedback_sitecourse_map.
1562  *  @param int $feedbackid
1563  *  @return array the course-records
1564  */
1565 function feedback_get_courses_from_sitecourse_map($feedbackid) {
1566     global $CFG;
1567     
1568     $sql = "select f.id, f.courseid, c.fullname, c.shortname
1569                 from {$CFG->prefix}feedback_sitecourse_map f, {$CFG->prefix}course c
1570                 where c.id = f.courseid
1571                 and f.feedbackid = $feedbackid
1572                 order by c.fullname";
1573     
1574     return get_records_sql($sql);
1575     
1578 /** 
1579  *  removes non existing courses or feedbacks from sitecourse_map.
1580  *  it shouldn't be called all too often
1581  *  a good place for it could be the mapcourse.php or unmapcourse.php
1582  *  @return void
1583  */
1584 function feedback_clean_up_sitecourse_map() {
1585     $maps = get_records('feedback_sitecourse_map');
1586     foreach($maps as $map) {
1587         if(!get_record('course', 'id', $map->courseid)) {
1588             delete_records('feedback_sitecourse_map', 'courseid', $map->courseid, 'feedbackid', $map->feedbackid);
1589             continue;
1590         }
1591         if(!get_record('feedback', 'id', $map->feedbackid)) {
1592             delete_records('feedback_sitecourse_map', 'courseid', $map->courseid, 'feedbackid', $map->feedbackid);
1593             continue;
1594         }
1595         
1596     }
1599 ////////////////////////////////////////////////
1600 ////////////////////////////////////////////////
1601 ////////////////////////////////////////////////
1602 //not relatable functions
1603 ////////////////////////////////////////////////
1605 /** 
1606  *  prints the option items of a selection-input item (dropdownlist).
1607  *  @param int $startval the first value of the list
1608  *  @param int $endval the last value of the list
1609  *  @param int $selectval which item should be selected
1610  *  @param int $interval the stepsize from the first to the last value
1611  *  @return void
1612  */
1613 function feedback_print_numeric_option_list($startval, $endval, $selectval = '', $interval = 1){
1614     for($i = $startval; $i <= $endval; $i += $interval){
1615         if($selectval == ($i)){
1616             $selected = 'selected="selected"';
1617         }else{
1618             $selected = '';
1619         }
1620         echo '<option '.$selected.'>'.$i.'</option>';
1621     }
1624 /** 
1625  *  sends an email to the teachers of the course where the given feedback is placed.
1626  *  @param object $cm the coursemodule-record
1627  *  @param $feedback
1628  *  @param $course
1629  *  @param $userid
1630  *  @return void
1631  */
1632 function feedback_send_email($cm, $feedback, $course, $userid) {
1633     
1634     global $CFG;
1635     
1636     if ($feedback->email_notification == 0) {  // No need to do anything
1637         return;
1638     }
1639     
1640     $user = get_record('user', 'id', $userid);
1641     
1642     if (groupmode($course, $cm) == SEPARATEGROUPS) {    // Separate groups are being used
1643         $groups = get_records_sql_menu("SELECT g.name, g.id
1644                                           FROM {$CFG->prefix}groups g,
1645                                                  {$CFG->prefix}groups_members m
1646                                           WHERE g.courseid = '$course->id'
1647                                              AND g.id = m.groupid
1648                                              AND m.userid = '$userid'
1649                                              ORDER BY name ASC");
1650         $groups = array_values($groups);
1651         
1652         $teachers = feedback_get_receivemail_users($cm->id, $groups);
1653     } else {
1654         $teachers = feedback_get_receivemail_users($cm->id);
1655     }
1656     
1657     if ($teachers) {
1659         $strfeedbacks = get_string('modulenameplural', 'feedback');
1660         $strfeedback  = get_string('modulename', 'feedback');
1661         $strcompleted  = get_string('completed', 'feedback');
1662         $printusername = $feedback->anonymous == FEEDBACK_ANONYMOUS_NO ? fullname($user) : get_string('anonymous_user', 'feedback');
1663         
1664         foreach ($teachers as $teacher) {
1665             unset($info);
1666             $info->username = $printusername;
1667             $info->feedback = format_string($feedback->name,true);
1668             $info->url = $CFG->wwwroot.'/mod/feedback/show_entries.php?id='.$cm->id.'&userid='.$userid.'&do_show=showentries';
1670             $postsubject = $strcompleted.': '.$info->username.' -> '.$feedback->name;
1671             $posttext = feedback_send_email_text($info, $course);
1672             $posthtml = ($teacher->mailformat == 1) ? feedback_send_email_html($info, $course, $cm) : '';
1673             
1674             if($feedback->anonymous == FEEDBACK_ANONYMOUS_NO) {
1675                 @email_to_user($teacher, $user, $postsubject, $posttext, $posthtml);
1676             }else {
1677                 @email_to_user($teacher, $teacher, $postsubject, $posttext, $posthtml);
1678             }
1679         }
1680     }
1683 /** 
1684  *  sends an email to the teachers of the course where the given feedback is placed.
1685  *  @param object $cm the coursemodule-record
1686  *  @param $feedback
1687  *  @param $course
1688  *  @return void
1689  */
1690 function feedback_send_email_anonym($cm, $feedback, $course) {
1691     
1692     global $CFG;
1693     
1694     if ($feedback->email_notification == 0) {             // No need to do anything
1695         return;
1696     }
1697     
1698     // $teachers = get_course_teachers($course->id);
1699     $teachers = feedback_get_receivemail_users($cm->id);
1701     if ($teachers) {
1703         $strfeedbacks = get_string('modulenameplural', 'feedback');
1704         $strfeedback  = get_string('modulename', 'feedback');
1705         $strcompleted  = get_string('completed', 'feedback');
1706         $printusername = get_string('anonymous_user', 'feedback');
1707         
1708         foreach ($teachers as $teacher) {
1709             unset($info);
1710             $info->username = $printusername;
1711             $info->feedback = format_string($feedback->name,true);
1712             $info->url = $CFG->wwwroot.'/mod/feedback/show_entries_anonym.php?id='.$cm->id;
1714             $postsubject = $strcompleted.': '.$info->username.' -> '.$feedback->name;
1715             $posttext = feedback_send_email_text($info, $course);
1716             $posthtml = ($teacher->mailformat == 1) ? feedback_send_email_html($info, $course, $cm) : '';
1717             
1718             @email_to_user($teacher, $teacher, $postsubject, $posttext, $posthtml);
1719         }
1720     }
1723 /** 
1724  *  send the text-part of the email
1725  *  @param object $info includes some infos about the feedback you want to send
1726  *  @param object $course
1727  *  @return string the text you want to post
1728  */
1729 function feedback_send_email_text($info, $course) {
1730     $posttext  = $course->shortname.' -> '.get_string('modulenameplural', 'feedback').' -> '.
1731                     $info->feedback."\n";
1732     $posttext .= '---------------------------------------------------------------------'."\n";
1733     $posttext .= get_string("emailteachermail", "feedback", $info)."\n";
1734     $posttext .= '---------------------------------------------------------------------'."\n";
1735     return $posttext;
1739 /** 
1740  *  send the html-part of the email
1741  *  @param object $info includes some infos about the feedback you want to send
1742  *  @param object $course
1743  *  @return string the text you want to post
1744  */
1745 function feedback_send_email_html($info, $course, $cm) {
1746     global $CFG;
1747     $posthtml  = '<p><font face="sans-serif">'.
1748                 '<a href="'.$CFG->wwwroot.htmlspecialchars('/course/view.php?id='.$course->id).'">'.$course->shortname.'</a> ->'.
1749                 '<a href="'.$CFG->wwwroot.htmlspecialchars('/mod/feedback/index.php?id='.$course->id).'">'.get_string('modulenameplural', 'feedback').'</a> ->'.
1750                 '<a href="'.$CFG->wwwroot.htmlspecialchars('/mod/feedback/view.php?id='.$cm->id).'">'.$info->feedback.'</a></font></p>';
1751     $posthtml .= '<hr /><font face="sans-serif">';
1752     $posthtml .= '<p>'.get_string('emailteachermailhtml', 'feedback', $info).'</p>';
1753     $posthtml .= '</font><hr />';
1754     return $posthtml;
1757 /** 
1758  *  print some errors to inform users about this.
1759  *  @return void
1760  */
1761 function feedback_print_errors() {
1762  
1763     global $SESSION;
1764                 
1765     if(empty($SESSION->feedback->errors)) {
1766                 return;
1767     }
1769     // print_simple_box_start("center", "60%", "#FFAAAA", 20, "noticebox");
1770     print_box_start('generalbox errorboxcontent boxaligncenter boxwidthnormal');
1771     print_heading(get_string('handling_error', 'feedback'));
1773     echo '<p align="center"><b><font color="black"><pre>';
1774     print_r($SESSION->feedback->errors) . "\n";
1775     echo '</pre></font></b></p>';
1776         
1777     // print_simple_box_end();
1778     print_box_end();
1779     echo '<br /><br />';
1780     $SESSION->feedback->errors = array(); //remove errors
1781
1783 function feedback_encode_target_url($url) {
1784     if (strpos($url, '?')) {
1785         list($part1, $part2) = explode('?', $url, 2); //maximal 2 parts
1786         return $part1 . '?' . htmlentities($part2);
1787     } else {
1788         return $url;
1789     }
1791 ?>