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